@dignetwork/dig-sdk 0.0.1-alpha.100 → 0.0.1-alpha.102
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.
- package/dist/DigNetwork/ContentServer.d.ts +6 -4
- package/dist/DigNetwork/ContentServer.d.ts.map +1 -1
- package/dist/DigNetwork/ContentServer.js +206 -73
- package/dist/DigNetwork/IncentiveServer.d.ts.map +1 -1
- package/dist/DigNetwork/IncentiveServer.js +6 -5
- package/dist/DigNetwork/PropagationServer.d.ts.map +1 -1
- package/dist/DigNetwork/PropagationServer.js +9 -8
- package/dist/utils/network.d.ts +1 -0
- package/dist/utils/network.d.ts.map +1 -1
- package/dist/utils/network.js +12 -1
- package/package.json +1 -1
|
@@ -1,10 +1,11 @@
|
|
|
1
|
+
import http from "http";
|
|
2
|
+
import { Readable } from "stream";
|
|
1
3
|
export declare class ContentServer {
|
|
2
4
|
private ipAddress;
|
|
3
5
|
private storeId;
|
|
4
6
|
private static certPath;
|
|
5
7
|
private static keyPath;
|
|
6
8
|
private static readonly port;
|
|
7
|
-
private static readonly inactivityTimeout;
|
|
8
9
|
constructor(ipAddress: string, storeId: string);
|
|
9
10
|
getKey(key: string, rootHash: string, challengeHex?: string): Promise<string>;
|
|
10
11
|
getPaymentAddress(): Promise<string | null>;
|
|
@@ -14,18 +15,19 @@ export declare class ContentServer {
|
|
|
14
15
|
getKeysIndex(rootHash?: string): Promise<any>;
|
|
15
16
|
headKey(key: string, rootHash?: string): Promise<{
|
|
16
17
|
success: boolean;
|
|
17
|
-
headers?:
|
|
18
|
+
headers?: http.IncomingHttpHeaders;
|
|
18
19
|
}>;
|
|
19
20
|
headStore(options?: {
|
|
20
21
|
hasRootHash: string;
|
|
21
22
|
}): Promise<{
|
|
22
23
|
success: boolean;
|
|
23
|
-
headers?:
|
|
24
|
+
headers?: http.IncomingHttpHeaders;
|
|
24
25
|
}>;
|
|
25
26
|
hasRootHash(rootHash: string): Promise<boolean>;
|
|
27
|
+
streamKey(key: string, rootHash?: string): Promise<Readable>;
|
|
26
28
|
private head;
|
|
27
29
|
private fetchJson;
|
|
30
|
+
private fetchWithRetries;
|
|
28
31
|
private fetch;
|
|
29
|
-
private getAxiosConfig;
|
|
30
32
|
}
|
|
31
33
|
//# sourceMappingURL=ContentServer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ContentServer.d.ts","sourceRoot":"","sources":["../../src/DigNetwork/ContentServer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ContentServer.d.ts","sourceRoot":"","sources":["../../src/DigNetwork/ContentServer.ts"],"names":[],"mappings":"AACA,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAIlC,qBAAa,aAAa;IACxB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAS;IAChC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAS;IAC/B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAQ;gBAExB,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;IAYjC,MAAM,CACjB,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,EAChB,YAAY,CAAC,EAAE,MAAM,GACpB,OAAO,CAAC,MAAM,CAAC;IAaL,iBAAiB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAe3C,YAAY,IAAI,OAAO,CAAC,GAAG,CAAC;IAM5B,cAAc,IAAI,OAAO,CAAC,GAAG,CAAC;IAM9B,cAAc,IAAI,OAAO,CAAC,GAAG,CAAC;IAM9B,YAAY,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC;IAY7C,OAAO,CAClB,GAAG,EAAE,MAAM,EACX,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,IAAI,CAAC,mBAAmB,CAAA;KAAE,CAAC;IAYvD,SAAS,CAAC,OAAO,CAAC,EAAE;QAAE,WAAW,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;QACjE,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,CAAC,EAAE,IAAI,CAAC,mBAAmB,CAAC;KACpC,CAAC;IAUW,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAUrD,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;YAgDrD,IAAI;YA0EJ,SAAS;YAMT,gBAAgB;YAiChB,KAAK;CA6GpB"}
|
|
@@ -4,10 +4,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.ContentServer = void 0;
|
|
7
|
-
const axios_1 = __importDefault(require("axios"));
|
|
8
7
|
const fs_1 = __importDefault(require("fs"));
|
|
9
|
-
const
|
|
8
|
+
const http_1 = __importDefault(require("http"));
|
|
9
|
+
const url_1 = require("url");
|
|
10
10
|
const ssl_1 = require("../utils/ssl");
|
|
11
|
+
const network_1 = require("../utils/network");
|
|
11
12
|
class ContentServer {
|
|
12
13
|
constructor(ipAddress, storeId) {
|
|
13
14
|
this.ipAddress = ipAddress;
|
|
@@ -20,11 +21,13 @@ class ContentServer {
|
|
|
20
21
|
}
|
|
21
22
|
// Method to get the content of a specified key from the peer, with optional challenge query
|
|
22
23
|
async getKey(key, rootHash, challengeHex) {
|
|
23
|
-
|
|
24
|
+
// Construct the base URL
|
|
25
|
+
let url = `https://${(0, network_1.formatHost)(this.ipAddress)}:${ContentServer.port}/chia.${this.storeId}.${rootHash}/${key}`;
|
|
26
|
+
// If a challenge is provided, append it as a query parameter
|
|
24
27
|
if (challengeHex) {
|
|
25
28
|
url += `?challenge=${challengeHex}`;
|
|
26
29
|
}
|
|
27
|
-
return this.
|
|
30
|
+
return this.fetchWithRetries(url);
|
|
28
31
|
}
|
|
29
32
|
// Method to get the payment address from the peer
|
|
30
33
|
async getPaymentAddress() {
|
|
@@ -40,17 +43,17 @@ class ContentServer {
|
|
|
40
43
|
}
|
|
41
44
|
// Method to get the .well-known information
|
|
42
45
|
async getWellKnown() {
|
|
43
|
-
const url = `https://${this.ipAddress}:${ContentServer.port}/.well-known`;
|
|
46
|
+
const url = `https://${(0, network_1.formatHost)(this.ipAddress)}:${ContentServer.port}/.well-known`;
|
|
44
47
|
return this.fetchJson(url);
|
|
45
48
|
}
|
|
46
49
|
// Method to get the list of known stores
|
|
47
50
|
async getKnownStores() {
|
|
48
|
-
const url = `https://${this.ipAddress}:${ContentServer.port}/.well-known/stores`;
|
|
51
|
+
const url = `https://${(0, network_1.formatHost)(this.ipAddress)}:${ContentServer.port}/.well-known/stores`;
|
|
49
52
|
return this.fetchJson(url);
|
|
50
53
|
}
|
|
51
54
|
// Method to get the index of all stores
|
|
52
55
|
async getStoresIndex() {
|
|
53
|
-
const url = `https://${this.ipAddress}:${ContentServer.port}/`;
|
|
56
|
+
const url = `https://${(0, network_1.formatHost)(this.ipAddress)}:${ContentServer.port}/`;
|
|
54
57
|
return this.fetchJson(url);
|
|
55
58
|
}
|
|
56
59
|
// Method to get the index of keys in a store
|
|
@@ -59,7 +62,7 @@ class ContentServer {
|
|
|
59
62
|
if (rootHash) {
|
|
60
63
|
udi += `.${rootHash}`;
|
|
61
64
|
}
|
|
62
|
-
const url = `https://${this.ipAddress}:${ContentServer.port}/${udi}`;
|
|
65
|
+
const url = `https://${(0, network_1.formatHost)(this.ipAddress)}:${ContentServer.port}/${udi}`;
|
|
63
66
|
return this.fetchJson(url);
|
|
64
67
|
}
|
|
65
68
|
// Method to check if a specific key exists (HEAD request)
|
|
@@ -68,12 +71,12 @@ class ContentServer {
|
|
|
68
71
|
if (rootHash) {
|
|
69
72
|
udi += `.${rootHash}`;
|
|
70
73
|
}
|
|
71
|
-
const url = `https://${this.ipAddress}:${ContentServer.port}/${udi}/${key}`;
|
|
74
|
+
const url = `https://${(0, network_1.formatHost)(this.ipAddress)}:${ContentServer.port}/${udi}/${key}`;
|
|
72
75
|
return this.head(url);
|
|
73
76
|
}
|
|
74
77
|
// Method to check if a specific store exists (HEAD request)
|
|
75
78
|
async headStore(options) {
|
|
76
|
-
let url = `https://${this.ipAddress}:${ContentServer.port}/chia.${this.storeId}`;
|
|
79
|
+
let url = `https://${(0, network_1.formatHost)(this.ipAddress)}:${ContentServer.port}/chia.${this.storeId}`;
|
|
77
80
|
if (options?.hasRootHash) {
|
|
78
81
|
url += `?hasRootHash=${options.hasRootHash}`;
|
|
79
82
|
}
|
|
@@ -88,89 +91,219 @@ class ContentServer {
|
|
|
88
91
|
}
|
|
89
92
|
return false;
|
|
90
93
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
const response = await axios_1.default.head(url, config);
|
|
96
|
-
return {
|
|
97
|
-
success: response.status >= 200 && response.status < 300,
|
|
98
|
-
headers: response.headers,
|
|
99
|
-
};
|
|
100
|
-
}
|
|
101
|
-
catch (error) {
|
|
102
|
-
return { success: false };
|
|
94
|
+
streamKey(key, rootHash) {
|
|
95
|
+
let udi = `chia.${this.storeId}`;
|
|
96
|
+
if (rootHash) {
|
|
97
|
+
udi += `.${rootHash}`;
|
|
103
98
|
}
|
|
99
|
+
return new Promise((resolve, reject) => {
|
|
100
|
+
const url = `https://${(0, network_1.formatHost)(this.ipAddress)}:${ContentServer.port}/${udi}/${key}`;
|
|
101
|
+
const urlObj = new url_1.URL(url);
|
|
102
|
+
const requestOptions = {
|
|
103
|
+
hostname: urlObj.hostname,
|
|
104
|
+
port: urlObj.port || ContentServer.port,
|
|
105
|
+
path: urlObj.pathname + urlObj.search,
|
|
106
|
+
method: "GET",
|
|
107
|
+
};
|
|
108
|
+
const request = http_1.default.request(requestOptions, (response) => {
|
|
109
|
+
if (response.statusCode === 200) {
|
|
110
|
+
resolve(response); // Resolve with the readable stream
|
|
111
|
+
}
|
|
112
|
+
else if (response.statusCode === 301 || response.statusCode === 302) {
|
|
113
|
+
// Handle redirects
|
|
114
|
+
const redirectUrl = response.headers.location;
|
|
115
|
+
if (redirectUrl) {
|
|
116
|
+
this.streamKey(redirectUrl).then(resolve).catch(reject);
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
reject(new Error("Redirected without a location header"));
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
reject(new Error(`Failed to retrieve data from ${url}. Status code: ${response.statusCode}`));
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
request.on("error", (error) => {
|
|
127
|
+
console.error(`GET Request error for ${url}:`, error);
|
|
128
|
+
reject(error);
|
|
129
|
+
});
|
|
130
|
+
request.end();
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
// Helper method to perform HEAD requests
|
|
134
|
+
async head(url, maxRedirects = 5) {
|
|
135
|
+
return new Promise((resolve, reject) => {
|
|
136
|
+
try {
|
|
137
|
+
// Parse the input URL
|
|
138
|
+
const urlObj = new url_1.URL(url);
|
|
139
|
+
const requestOptions = {
|
|
140
|
+
hostname: urlObj.hostname,
|
|
141
|
+
port: urlObj.port ||
|
|
142
|
+
(urlObj.protocol === "http:" ? 80 : ContentServer.port),
|
|
143
|
+
path: urlObj.pathname + urlObj.search,
|
|
144
|
+
method: "HEAD",
|
|
145
|
+
key: fs_1.default.readFileSync(ContentServer.keyPath),
|
|
146
|
+
cert: fs_1.default.readFileSync(ContentServer.certPath),
|
|
147
|
+
rejectUnauthorized: false,
|
|
148
|
+
};
|
|
149
|
+
const request = http_1.default.request(requestOptions, (response) => {
|
|
150
|
+
const { statusCode, headers } = response;
|
|
151
|
+
// If status code is 2xx, return success
|
|
152
|
+
if (statusCode && statusCode >= 200 && statusCode < 300) {
|
|
153
|
+
resolve({ success: true, headers });
|
|
154
|
+
}
|
|
155
|
+
// Handle 3xx redirection
|
|
156
|
+
else if (statusCode &&
|
|
157
|
+
statusCode >= 300 &&
|
|
158
|
+
statusCode < 400 &&
|
|
159
|
+
headers.location) {
|
|
160
|
+
if (maxRedirects > 0) {
|
|
161
|
+
let redirectUrl = headers.location;
|
|
162
|
+
// Check if the redirect URL is relative
|
|
163
|
+
if (!/^https?:\/\//i.test(redirectUrl)) {
|
|
164
|
+
// Resolve the relative URL based on the original URL
|
|
165
|
+
redirectUrl = new url_1.URL(redirectUrl, url).toString();
|
|
166
|
+
console.log(`Resolved relative redirect to: ${redirectUrl}`);
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
console.log(`Redirecting to: ${redirectUrl}`);
|
|
170
|
+
}
|
|
171
|
+
// Recursively follow the redirection
|
|
172
|
+
this.head(redirectUrl, maxRedirects - 1)
|
|
173
|
+
.then(resolve)
|
|
174
|
+
.catch(reject);
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
reject({ success: false, message: "Too many redirects" });
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
// For other status codes, consider it a failure
|
|
182
|
+
resolve({ success: false });
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
request.on("error", (error) => {
|
|
186
|
+
console.error(`HEAD ${url}:`, error.message);
|
|
187
|
+
reject({ success: false });
|
|
188
|
+
});
|
|
189
|
+
request.end();
|
|
190
|
+
}
|
|
191
|
+
catch (err) {
|
|
192
|
+
console.error(`Invalid URL: ${url}`, err);
|
|
193
|
+
reject({ success: false, message: "Invalid URL" });
|
|
194
|
+
}
|
|
195
|
+
});
|
|
104
196
|
}
|
|
105
197
|
// Helper method to fetch JSON data from a URL
|
|
106
198
|
async fetchJson(url) {
|
|
107
|
-
const response = await this.
|
|
199
|
+
const response = await this.fetchWithRetries(url);
|
|
108
200
|
return JSON.parse(response);
|
|
109
201
|
}
|
|
110
|
-
//
|
|
111
|
-
async
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
const
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
202
|
+
// Helper method to fetch content with retries and redirection handling
|
|
203
|
+
async fetchWithRetries(url) {
|
|
204
|
+
let attempt = 0;
|
|
205
|
+
const maxRetries = 1;
|
|
206
|
+
const initialDelay = 2000; // 2 seconds
|
|
207
|
+
const maxDelay = 10000; // 10 seconds
|
|
208
|
+
const delayMultiplier = 1.5;
|
|
209
|
+
let delay = initialDelay;
|
|
210
|
+
while (attempt < maxRetries) {
|
|
211
|
+
try {
|
|
212
|
+
return await this.fetch(url);
|
|
213
|
+
}
|
|
214
|
+
catch (error) {
|
|
215
|
+
if (attempt < maxRetries - 1) {
|
|
216
|
+
console.warn(`Attempt ${attempt + 1} failed: ${error.message}. Retrying in ${delay / 1000} seconds...`);
|
|
217
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
218
|
+
delay = Math.min(maxDelay, delay * delayMultiplier);
|
|
120
219
|
}
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
220
|
+
else {
|
|
221
|
+
console.error(`Failed to retrieve data from ${url}. Aborting.`);
|
|
222
|
+
throw new Error(`Failed to retrieve data: ${error.message}`);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
attempt++;
|
|
226
|
+
}
|
|
227
|
+
throw new Error(`Failed to retrieve data from ${url} after ${maxRetries} attempts.`);
|
|
228
|
+
}
|
|
229
|
+
// Core method to fetch content from a URL with a 5-second inactivity timeout
|
|
230
|
+
async fetch(url, maxRedirects = 5) {
|
|
231
|
+
return new Promise((resolve, reject) => {
|
|
232
|
+
const urlObj = new url_1.URL(url);
|
|
233
|
+
const timeoutDuration = 5000; // 5 seconds
|
|
234
|
+
let timeout = null; // Initialize timeout
|
|
235
|
+
const requestOptions = {
|
|
236
|
+
hostname: urlObj.hostname,
|
|
237
|
+
port: urlObj.port || ContentServer.port,
|
|
238
|
+
path: urlObj.pathname + urlObj.search, // Include query params
|
|
239
|
+
method: "GET",
|
|
240
|
+
key: fs_1.default.readFileSync(ContentServer.keyPath),
|
|
241
|
+
cert: fs_1.default.readFileSync(ContentServer.certPath),
|
|
242
|
+
rejectUnauthorized: false,
|
|
124
243
|
};
|
|
125
|
-
|
|
126
|
-
.get(url, {
|
|
127
|
-
...config,
|
|
128
|
-
cancelToken: source.token,
|
|
129
|
-
responseType: "stream", // Use stream to track data transfer
|
|
130
|
-
maxRedirects: 5, // Axios follows up to 5 redirects by default
|
|
131
|
-
})
|
|
132
|
-
.then((response) => {
|
|
244
|
+
const request = http_1.default.request(requestOptions, (response) => {
|
|
133
245
|
let data = "";
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
246
|
+
// Set timeout for inactivity
|
|
247
|
+
timeout = setTimeout(() => {
|
|
248
|
+
console.error(`Request timeout: No data received for ${timeoutDuration / 1000} seconds.`);
|
|
249
|
+
request.destroy(); // Use destroy instead of abort
|
|
250
|
+
reject(new Error(`Request timed out after ${timeoutDuration / 1000} seconds of inactivity`));
|
|
251
|
+
}, timeoutDuration);
|
|
252
|
+
const resetTimeout = () => {
|
|
139
253
|
if (timeout) {
|
|
140
|
-
clearTimeout(timeout);
|
|
254
|
+
clearTimeout(timeout);
|
|
141
255
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
256
|
+
timeout = setTimeout(() => {
|
|
257
|
+
console.error(`Request timeout: No data received for ${timeoutDuration / 1000} seconds.`);
|
|
258
|
+
request.destroy(); // Use destroy instead of abort
|
|
259
|
+
reject(new Error(`Request timed out after ${timeoutDuration / 1000} seconds of inactivity`));
|
|
260
|
+
}, timeoutDuration);
|
|
261
|
+
};
|
|
262
|
+
if (response.statusCode === 200) {
|
|
263
|
+
response.on("data", (chunk) => {
|
|
264
|
+
data += chunk;
|
|
265
|
+
resetTimeout(); // Reset the timeout every time data is received
|
|
266
|
+
});
|
|
267
|
+
response.on("end", () => {
|
|
268
|
+
if (timeout) {
|
|
269
|
+
clearTimeout(timeout);
|
|
270
|
+
}
|
|
271
|
+
resolve(data);
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
else if ((response.statusCode === 301 || response.statusCode === 302) &&
|
|
275
|
+
response.headers.location) {
|
|
276
|
+
// Handle redirects
|
|
277
|
+
if (maxRedirects > 0) {
|
|
278
|
+
const redirectUrl = new url_1.URL(response.headers.location, url); // Resolve relative URLs based on the original URL
|
|
279
|
+
if (timeout) {
|
|
280
|
+
clearTimeout(timeout);
|
|
281
|
+
}
|
|
282
|
+
this.fetch(redirectUrl.toString(), maxRedirects - 1)
|
|
283
|
+
.then(resolve)
|
|
284
|
+
.catch(reject);
|
|
285
|
+
}
|
|
286
|
+
else {
|
|
287
|
+
reject(new Error("Too many redirects"));
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
else {
|
|
145
291
|
if (timeout) {
|
|
146
292
|
clearTimeout(timeout);
|
|
147
293
|
}
|
|
148
|
-
reject(
|
|
149
|
-
});
|
|
150
|
-
})
|
|
151
|
-
.catch((error) => {
|
|
152
|
-
if (axios_1.default.isCancel(error)) {
|
|
153
|
-
console.error("Request canceled:", error.message);
|
|
294
|
+
reject(new Error(`Failed to retrieve data from ${url}. Status code: ${response.statusCode}`));
|
|
154
295
|
}
|
|
155
|
-
|
|
156
|
-
|
|
296
|
+
});
|
|
297
|
+
request.on("error", (error) => {
|
|
298
|
+
if (timeout) {
|
|
299
|
+
clearTimeout(timeout);
|
|
157
300
|
}
|
|
301
|
+
console.error(`GET ${url}:`, error.message);
|
|
158
302
|
reject(error);
|
|
159
303
|
});
|
|
304
|
+
request.end();
|
|
160
305
|
});
|
|
161
306
|
}
|
|
162
|
-
// Helper method to configure axios with HTTPS settings
|
|
163
|
-
getAxiosConfig() {
|
|
164
|
-
return {
|
|
165
|
-
httpsAgent: new https_1.default.Agent({
|
|
166
|
-
cert: fs_1.default.readFileSync(ContentServer.certPath),
|
|
167
|
-
key: fs_1.default.readFileSync(ContentServer.keyPath),
|
|
168
|
-
rejectUnauthorized: false,
|
|
169
|
-
}),
|
|
170
|
-
timeout: 0, // Disable axios timeout (we're using inactivity timeout)
|
|
171
|
-
};
|
|
172
|
-
}
|
|
173
307
|
}
|
|
174
308
|
exports.ContentServer = ContentServer;
|
|
175
309
|
ContentServer.port = 4161;
|
|
176
|
-
ContentServer.inactivityTimeout = 5000; // Inactivity timeout in milliseconds (5 seconds)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"IncentiveServer.d.ts","sourceRoot":"","sources":["../../src/DigNetwork/IncentiveServer.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"IncentiveServer.d.ts","sourceRoot":"","sources":["../../src/DigNetwork/IncentiveServer.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAGhD,qBAAa,eAAe;IAC1B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,IAAI,CAAgB;gBAEhB,SAAS,EAAE,MAAM;IAKhB,sBAAsB,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;IAOjE,sBAAsB,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;IAOjE,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOtD,uBAAuB,IAAI,OAAO,CAAC,oBAAoB,EAAE,CAAC;IAO1D,mBAAmB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC;YAOlE,WAAW;CA6C1B"}
|
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.IncentiveServer = void 0;
|
|
7
7
|
const https_1 = __importDefault(require("https"));
|
|
8
8
|
const url_1 = require("url");
|
|
9
|
+
const network_1 = require("../utils/network");
|
|
9
10
|
class IncentiveServer {
|
|
10
11
|
constructor(ipAddress) {
|
|
11
12
|
this.port = 4160;
|
|
@@ -13,27 +14,27 @@ class IncentiveServer {
|
|
|
13
14
|
}
|
|
14
15
|
// Method to create a new incentive program
|
|
15
16
|
async createIncentiveProgram(data) {
|
|
16
|
-
const url = `https://${this.ipAddress}:${this.port}/incentive`;
|
|
17
|
+
const url = `https://${(0, network_1.formatHost)(this.ipAddress)}:${this.port}/incentive`;
|
|
17
18
|
await this.makeRequest(url, "POST", data);
|
|
18
19
|
}
|
|
19
20
|
// Method to update an existing incentive program
|
|
20
21
|
async updateIncentiveProgram(data) {
|
|
21
|
-
const url = `https://${this.ipAddress}:${this.port}/incentive`;
|
|
22
|
+
const url = `https://${(0, network_1.formatHost)(this.ipAddress)}:${this.port}/incentive`;
|
|
22
23
|
await this.makeRequest(url, "PUT", data);
|
|
23
24
|
}
|
|
24
25
|
// Method to delete an incentive program by storeId
|
|
25
26
|
async deleteIncentiveProgram(storeId) {
|
|
26
|
-
const url = `https://${this.ipAddress}:${this.port}/incentive`;
|
|
27
|
+
const url = `https://${(0, network_1.formatHost)(this.ipAddress)}:${this.port}/incentive`;
|
|
27
28
|
await this.makeRequest(url, "DELETE", { storeId });
|
|
28
29
|
}
|
|
29
30
|
// Method to get all incentive programs
|
|
30
31
|
async getAllIncentivePrograms() {
|
|
31
|
-
const url = `https://${this.ipAddress}:${this.port}/incentive`;
|
|
32
|
+
const url = `https://${(0, network_1.formatHost)(this.ipAddress)}:${this.port}/incentive`;
|
|
32
33
|
return this.makeRequest(url, "GET");
|
|
33
34
|
}
|
|
34
35
|
// Method to get a specific incentive program by storeId
|
|
35
36
|
async getIncentiveProgram(storeId) {
|
|
36
|
-
const url = `https://${this.ipAddress}:${this.port}/incentive/${storeId}`;
|
|
37
|
+
const url = `https://${(0, network_1.formatHost)(this.ipAddress)}:${this.port}/incentive/${storeId}`;
|
|
37
38
|
return this.makeRequest(url, "GET");
|
|
38
39
|
}
|
|
39
40
|
// Helper method to handle the HTTPS request
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PropagationServer.d.ts","sourceRoot":"","sources":["../../src/DigNetwork/PropagationServer.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,MAAM,OAAO,CAAC;AAW1B,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"PropagationServer.d.ts","sourceRoot":"","sources":["../../src/DigNetwork/PropagationServer.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,MAAM,OAAO,CAAC;AAW1B,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAkBrC,qBAAa,iBAAiB;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,GAAG,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IAE7B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAQ;IACpC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAAQ;gBAErC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;IAY9C;;OAEG;IACG,gBAAgB;IAOtB;;OAEG;IACH,gBAAgB;IAQhB;;OAEG;IACH,oBAAoB,CAAC,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM;IAyB3D;;OAEG;IACG,gBAAgB,CACpB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC;QAAE,WAAW,EAAE,OAAO,CAAC;QAAC,cAAc,EAAE,OAAO,CAAA;KAAE,CAAC;IA0C7D;;OAEG;IACG,kBAAkB,CAAC,QAAQ,EAAE,MAAM;IAuDzC;;OAEG;IACG,YAAY,CAChB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,OAAO,CAAA;KAAE,CAAC;IAyBlD;;;OAGG;IACG,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;IAuGhD;;OAEG;IACG,mBAAmB;IAgCzB;;OAEG;WACU,WAAW,CACtB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM;IA2DnB;;;OAGG;IACG,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAgFlD;;OAEG;IACG,cAAc,CAClB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IA0B7C;;;OAGG;IACG,YAAY,CAChB,KAAK,EAAE,MAAM,EACb,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM;IAwGjB;;OAEG;WACU,aAAa,CACxB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM;CA2FpB"}
|
|
@@ -23,6 +23,7 @@ const stream_1 = require("stream");
|
|
|
23
23
|
const credentialsUtils_1 = require("../utils/credentialsUtils");
|
|
24
24
|
const config_1 = require("../utils/config");
|
|
25
25
|
const blockchain_1 = require("../blockchain");
|
|
26
|
+
const network_1 = require("../utils/network");
|
|
26
27
|
// Helper function to trim long filenames with ellipsis and ensure consistent padding
|
|
27
28
|
function formatFilename(filename, maxLength = 30) {
|
|
28
29
|
if (!filename) {
|
|
@@ -90,7 +91,7 @@ class PropagationServer {
|
|
|
90
91
|
const config = {
|
|
91
92
|
httpsAgent: this.createHttpsAgent(),
|
|
92
93
|
};
|
|
93
|
-
let url = `https://${this.ipAddress}:${PropagationServer.port}/${this.storeId}`;
|
|
94
|
+
let url = `https://${(0, network_1.formatHost)(this.ipAddress)}:${PropagationServer.port}/${this.storeId}`;
|
|
94
95
|
if (rootHash) {
|
|
95
96
|
url += `?hasRootHash=${rootHash}`;
|
|
96
97
|
}
|
|
@@ -144,7 +145,7 @@ class PropagationServer {
|
|
|
144
145
|
password: this.password,
|
|
145
146
|
};
|
|
146
147
|
}
|
|
147
|
-
const url = `https://${this.ipAddress}:${PropagationServer.port}/upload/${this.storeId}?roothash=${rootHash}`;
|
|
148
|
+
const url = `https://${(0, network_1.formatHost)(this.ipAddress)}:${PropagationServer.port}/upload/${this.storeId}?roothash=${rootHash}`;
|
|
148
149
|
const response = await axios_1.default.post(url, formData, config);
|
|
149
150
|
this.sessionId = response.data.sessionId;
|
|
150
151
|
spinner.success({
|
|
@@ -165,7 +166,7 @@ class PropagationServer {
|
|
|
165
166
|
const config = {
|
|
166
167
|
httpsAgent: this.createHttpsAgent(),
|
|
167
168
|
};
|
|
168
|
-
const url = `https://${this.ipAddress}:${PropagationServer.port}/upload/${this.storeId}/${this.sessionId}/${filename}`;
|
|
169
|
+
const url = `https://${(0, network_1.formatHost)(this.ipAddress)}:${PropagationServer.port}/upload/${this.storeId}/${this.sessionId}/${filename}`;
|
|
169
170
|
const response = await axios_1.default.head(url, config);
|
|
170
171
|
// Check for 'x-file-exists' header
|
|
171
172
|
const fileExists = response.headers["x-file-exists"] === "true";
|
|
@@ -239,7 +240,7 @@ class PropagationServer {
|
|
|
239
240
|
maxContentLength: Infinity,
|
|
240
241
|
maxBodyLength: Infinity,
|
|
241
242
|
};
|
|
242
|
-
const url = `https://${this.ipAddress}:${PropagationServer.port}/upload/${this.storeId}/${this.sessionId}/${dataPath}`;
|
|
243
|
+
const url = `https://${(0, network_1.formatHost)(this.ipAddress)}:${PropagationServer.port}/upload/${this.storeId}/${this.sessionId}/${dataPath}`;
|
|
243
244
|
// Create a promise that resolves when the progress stream ends
|
|
244
245
|
const progressPromise = new Promise((resolve, reject) => {
|
|
245
246
|
progressStream.on("end", resolve);
|
|
@@ -274,7 +275,7 @@ class PropagationServer {
|
|
|
274
275
|
}
|
|
275
276
|
: undefined,
|
|
276
277
|
};
|
|
277
|
-
const url = `https://${this.ipAddress}:${PropagationServer.port}/commit/${this.storeId}/${this.sessionId}`;
|
|
278
|
+
const url = `https://${(0, network_1.formatHost)(this.ipAddress)}:${PropagationServer.port}/commit/${this.storeId}/${this.sessionId}`;
|
|
278
279
|
const response = await axios_1.default.post(url, {}, config);
|
|
279
280
|
spinner.success({
|
|
280
281
|
text: (0, colorette_1.green)(`Upload session ${this.sessionId} successfully committed.`),
|
|
@@ -330,7 +331,7 @@ class PropagationServer {
|
|
|
330
331
|
* Logs progress using a local cli-progress bar.
|
|
331
332
|
*/
|
|
332
333
|
async fetchFile(dataPath) {
|
|
333
|
-
const url = `https://${this.ipAddress}:${PropagationServer.port}/fetch/${this.storeId}/${dataPath}`;
|
|
334
|
+
const url = `https://${(0, network_1.formatHost)(this.ipAddress)}:${PropagationServer.port}/fetch/${this.storeId}/${dataPath}`;
|
|
334
335
|
const config = {
|
|
335
336
|
responseType: "stream",
|
|
336
337
|
httpsAgent: this.createHttpsAgent(),
|
|
@@ -397,7 +398,7 @@ class PropagationServer {
|
|
|
397
398
|
const config = {
|
|
398
399
|
httpsAgent: this.createHttpsAgent(),
|
|
399
400
|
};
|
|
400
|
-
const url = `https://${this.ipAddress}:${PropagationServer.port}/store/${this.storeId}/${rootHash}/${dataPath}`;
|
|
401
|
+
const url = `https://${(0, network_1.formatHost)(this.ipAddress)}:${PropagationServer.port}/store/${this.storeId}/${rootHash}/${dataPath}`;
|
|
401
402
|
const response = await axios_1.default.head(url, config);
|
|
402
403
|
// Check the headers for file existence and size
|
|
403
404
|
const fileExists = response.headers["x-file-exists"] === "true";
|
|
@@ -417,7 +418,7 @@ class PropagationServer {
|
|
|
417
418
|
* Logs progress using a local cli-progress bar.
|
|
418
419
|
*/
|
|
419
420
|
async downloadFile(label, dataPath, rootHash, baseDir) {
|
|
420
|
-
const url = `https://${this.ipAddress}:${PropagationServer.port}/fetch/${this.storeId}/${dataPath}`;
|
|
421
|
+
const url = `https://${(0, network_1.formatHost)(this.ipAddress)}:${PropagationServer.port}/fetch/${this.storeId}/${dataPath}`;
|
|
421
422
|
let downloadPath = path_1.default.join(baseDir, dataPath);
|
|
422
423
|
// Ensure that the directory for the file exists
|
|
423
424
|
fs_1.default.mkdirSync(path_1.default.dirname(downloadPath), { recursive: true });
|
package/dist/utils/network.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"network.d.ts","sourceRoot":"","sources":["../../src/utils/network.ts"],"names":[],"mappings":"AAoBA,eAAO,MAAM,kBAAkB,QAAa,OAAO,CAAC,MAAM,GAAG,SAAS,CA6CrE,CAAC"}
|
|
1
|
+
{"version":3,"file":"network.d.ts","sourceRoot":"","sources":["../../src/utils/network.ts"],"names":[],"mappings":"AAoBA,eAAO,MAAM,kBAAkB,QAAa,OAAO,CAAC,MAAM,GAAG,SAAS,CA6CrE,CAAC;AAGF,eAAO,MAAM,UAAU,SAAU,MAAM,KAAG,MAUzC,CAAC"}
|
package/dist/utils/network.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.getPublicIpAddress = void 0;
|
|
6
|
+
exports.formatHost = exports.getPublicIpAddress = void 0;
|
|
7
7
|
/*
|
|
8
8
|
* Stopgap until better solution for finding public IPS found
|
|
9
9
|
*/
|
|
@@ -52,3 +52,14 @@ const getPublicIpAddress = async () => {
|
|
|
52
52
|
}
|
|
53
53
|
};
|
|
54
54
|
exports.getPublicIpAddress = getPublicIpAddress;
|
|
55
|
+
// Helper function to wrap IPv6 addresses in brackets
|
|
56
|
+
const formatHost = (host) => {
|
|
57
|
+
const ipv6Pattern = /^[a-fA-F0-9:]+$/; // Simple regex to match raw IPv6 addresses (without brackets)
|
|
58
|
+
const hasBrackets = /^\[.*\]$/; // Regex to check if the address already has brackets
|
|
59
|
+
// If it's an IPv6 address without brackets, add them
|
|
60
|
+
if (ipv6Pattern.test(host) && !hasBrackets.test(host)) {
|
|
61
|
+
return `[${host}]`;
|
|
62
|
+
}
|
|
63
|
+
return host; // Return the host as is (IPv4, hostname, or already bracketed IPv6)
|
|
64
|
+
};
|
|
65
|
+
exports.formatHost = formatHost;
|