@dignetwork/dig-sdk 0.0.1-alpha.2
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/LICENSE +7 -0
- package/dist/DataIntegrityTree/DataIntegrityTree.d.ts +160 -0
- package/dist/DataIntegrityTree/DataIntegrityTree.d.ts.map +1 -0
- package/dist/DataIntegrityTree/DataIntegrityTree.js +648 -0
- package/dist/DataIntegrityTree/DataLayerError.d.ts +6 -0
- package/dist/DataIntegrityTree/DataLayerError.d.ts.map +1 -0
- package/dist/DataIntegrityTree/DataLayerError.js +17 -0
- package/dist/DataIntegrityTree/index.d.ts +2 -0
- package/dist/DataIntegrityTree/index.d.ts.map +1 -0
- package/dist/DataIntegrityTree/index.js +17 -0
- package/dist/DigNetwork/ContentServer.d.ts +28 -0
- package/dist/DigNetwork/ContentServer.d.ts.map +1 -0
- package/dist/DigNetwork/ContentServer.js +243 -0
- package/dist/DigNetwork/DigChallenge.d.ts +82 -0
- package/dist/DigNetwork/DigChallenge.d.ts.map +1 -0
- package/dist/DigNetwork/DigChallenge.js +144 -0
- package/dist/DigNetwork/DigNetwork.d.ts +19 -0
- package/dist/DigNetwork/DigNetwork.d.ts.map +1 -0
- package/dist/DigNetwork/DigNetwork.js +222 -0
- package/dist/DigNetwork/DigPeer.d.ts +19 -0
- package/dist/DigNetwork/DigPeer.d.ts.map +1 -0
- package/dist/DigNetwork/DigPeer.js +164 -0
- package/dist/DigNetwork/IncentiveServer.d.ts +13 -0
- package/dist/DigNetwork/IncentiveServer.d.ts.map +1 -0
- package/dist/DigNetwork/IncentiveServer.js +76 -0
- package/dist/DigNetwork/PropagationServer.d.ts +41 -0
- package/dist/DigNetwork/PropagationServer.d.ts.map +1 -0
- package/dist/DigNetwork/PropagationServer.js +415 -0
- package/dist/DigNetwork/index.d.ts +4 -0
- package/dist/DigNetwork/index.d.ts.map +1 -0
- package/dist/DigNetwork/index.js +19 -0
- package/dist/blockchain/DataStore.d.ts +54 -0
- package/dist/blockchain/DataStore.d.ts.map +1 -0
- package/dist/blockchain/DataStore.js +410 -0
- package/dist/blockchain/DataStoreSerializer.d.ts +52 -0
- package/dist/blockchain/DataStoreSerializer.d.ts.map +1 -0
- package/dist/blockchain/DataStoreSerializer.js +109 -0
- package/dist/blockchain/FullNodePeer.d.ts +17 -0
- package/dist/blockchain/FullNodePeer.d.ts.map +1 -0
- package/dist/blockchain/FullNodePeer.js +215 -0
- package/dist/blockchain/ServerCoin.d.ts +21 -0
- package/dist/blockchain/ServerCoin.d.ts.map +1 -0
- package/dist/blockchain/ServerCoin.js +261 -0
- package/dist/blockchain/Wallet.d.ts +28 -0
- package/dist/blockchain/Wallet.d.ts.map +1 -0
- package/dist/blockchain/Wallet.js +220 -0
- package/dist/blockchain/coins.d.ts +6 -0
- package/dist/blockchain/coins.d.ts.map +1 -0
- package/dist/blockchain/coins.js +101 -0
- package/dist/blockchain/index.d.ts +8 -0
- package/dist/blockchain/index.d.ts.map +1 -0
- package/dist/blockchain/index.js +36 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/prompts.d.ts +21 -0
- package/dist/prompts.d.ts.map +1 -0
- package/dist/prompts.js +149 -0
- package/dist/types.d.ts +62 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/utils/FileCache.d.ts +11 -0
- package/dist/utils/FileCache.d.ts.map +1 -0
- package/dist/utils/FileCache.js +58 -0
- package/dist/utils/NconfManager.d.ts +11 -0
- package/dist/utils/NconfManager.d.ts.map +1 -0
- package/dist/utils/NconfManager.js +55 -0
- package/dist/utils/config.d.ts +67 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +223 -0
- package/dist/utils/connectionUtils.d.ts +10 -0
- package/dist/utils/connectionUtils.d.ts.map +1 -0
- package/dist/utils/connectionUtils.js +18 -0
- package/dist/utils/credentialsUtils.d.ts +8 -0
- package/dist/utils/credentialsUtils.d.ts.map +1 -0
- package/dist/utils/credentialsUtils.js +122 -0
- package/dist/utils/deltaUtils.d.ts +2 -0
- package/dist/utils/deltaUtils.d.ts.map +1 -0
- package/dist/utils/deltaUtils.js +83 -0
- package/dist/utils/directoryUtils.d.ts +15 -0
- package/dist/utils/directoryUtils.d.ts.map +1 -0
- package/dist/utils/directoryUtils.js +91 -0
- package/dist/utils/encryption.d.ts +8 -0
- package/dist/utils/encryption.d.ts.map +1 -0
- package/dist/utils/encryption.js +55 -0
- package/dist/utils/hashUtils.d.ts +8 -0
- package/dist/utils/hashUtils.d.ts.map +1 -0
- package/dist/utils/hashUtils.js +44 -0
- package/dist/utils/index.d.ts +14 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +29 -0
- package/dist/utils/network.d.ts +2 -0
- package/dist/utils/network.d.ts.map +1 -0
- package/dist/utils/network.js +38 -0
- package/dist/utils/spinnerUtils.d.ts +2 -0
- package/dist/utils/spinnerUtils.d.ts.map +1 -0
- package/dist/utils/spinnerUtils.js +47 -0
- package/dist/utils/ssl.d.ts +5 -0
- package/dist/utils/ssl.d.ts.map +1 -0
- package/dist/utils/ssl.js +50 -0
- package/dist/utils/validationUtils.d.ts +9 -0
- package/dist/utils/validationUtils.d.ts.map +1 -0
- package/dist/utils/validationUtils.js +55 -0
- package/package.json +64 -0
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.PropagationServer = void 0;
|
|
7
|
+
const fs_1 = __importDefault(require("fs"));
|
|
8
|
+
const https_1 = __importDefault(require("https"));
|
|
9
|
+
const url_1 = require("url");
|
|
10
|
+
const ssl_1 = require("../utils/ssl");
|
|
11
|
+
const credentialsUtils_1 = require("../utils/credentialsUtils");
|
|
12
|
+
const spinnerUtils_1 = require("../utils/spinnerUtils");
|
|
13
|
+
const blockchain_1 = require("../blockchain");
|
|
14
|
+
class PropagationServer {
|
|
15
|
+
constructor(ipAddress, storeId) {
|
|
16
|
+
this.ipAddress = ipAddress;
|
|
17
|
+
this.storeId = storeId;
|
|
18
|
+
if (!PropagationServer.certPath || !PropagationServer.keyPath) {
|
|
19
|
+
const { certPath, keyPath } = (0, ssl_1.getOrCreateSSLCerts)();
|
|
20
|
+
PropagationServer.certPath = certPath;
|
|
21
|
+
PropagationServer.keyPath = keyPath;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
// Method to upload a file to the propagation server
|
|
25
|
+
async pushFile(filePath, relativePath) {
|
|
26
|
+
const { nonce, username, password } = await this.getUploadDetails();
|
|
27
|
+
const wallet = await blockchain_1.Wallet.load("default");
|
|
28
|
+
const keyOwnershipSig = await wallet.createKeyOwnershipSignature(nonce);
|
|
29
|
+
const publicKey = await wallet.getPublicSyntheticKey();
|
|
30
|
+
const uploadUrl = `https://${this.ipAddress}:${PropagationServer.port}/${this.storeId}/${relativePath}`;
|
|
31
|
+
await this.retryOperation(() => this.uploadFileDirect(filePath, uploadUrl, username, password, keyOwnershipSig, publicKey.toString("hex"), nonce), `Upload failed for ${relativePath}`);
|
|
32
|
+
}
|
|
33
|
+
// Method to subscribe to a store on the propagation server
|
|
34
|
+
async subscribeToStore() {
|
|
35
|
+
const url = `https://${this.ipAddress}:${PropagationServer.port}/subscribe`;
|
|
36
|
+
const data = JSON.stringify({ storeId: this.storeId });
|
|
37
|
+
await this.postRequest(url, data);
|
|
38
|
+
}
|
|
39
|
+
// Method to unsubscribe from a store on the propagation server
|
|
40
|
+
async unsubscribeFromStore() {
|
|
41
|
+
const url = `https://${this.ipAddress}:${PropagationServer.port}/unsubscribe`;
|
|
42
|
+
const data = JSON.stringify({ storeId: this.storeId });
|
|
43
|
+
await this.postRequest(url, data);
|
|
44
|
+
}
|
|
45
|
+
// Method to check the status of a store on the propagation server
|
|
46
|
+
async getStoreStatus() {
|
|
47
|
+
const url = `https://${this.ipAddress}:${PropagationServer.port}/status/${this.storeId}`;
|
|
48
|
+
return this.fetchJson(url);
|
|
49
|
+
}
|
|
50
|
+
async streamStoreData(dataPath) {
|
|
51
|
+
const url = `https://${this.ipAddress}:${PropagationServer.port}/${this.storeId}/${dataPath}`;
|
|
52
|
+
return this.createReadStreamWithRetries(url);
|
|
53
|
+
}
|
|
54
|
+
// Method to retrieve a store's key
|
|
55
|
+
async getStoreData(dataPath) {
|
|
56
|
+
const url = `https://${this.ipAddress}:${PropagationServer.port}/${this.storeId}/${dataPath}`;
|
|
57
|
+
return this.fetch(url);
|
|
58
|
+
}
|
|
59
|
+
async getStatus() {
|
|
60
|
+
const url = `https://${this.ipAddress}:${PropagationServer.port}/status/${this.storeId}`;
|
|
61
|
+
const statusJson = await this.fetch(url);
|
|
62
|
+
return JSON.parse(statusJson);
|
|
63
|
+
}
|
|
64
|
+
// Method to check if a specific store exists (HEAD request)
|
|
65
|
+
async headStore() {
|
|
66
|
+
const url = `https://${this.ipAddress}:${PropagationServer.port}/${this.storeId}`;
|
|
67
|
+
return this.head(url);
|
|
68
|
+
}
|
|
69
|
+
// In PropagationServer.ts:
|
|
70
|
+
async isStoreSynced() {
|
|
71
|
+
const status = await this.getStatus();
|
|
72
|
+
return status.synced === true;
|
|
73
|
+
}
|
|
74
|
+
// Method to handle upload details including nonce
|
|
75
|
+
async getUploadDetails() {
|
|
76
|
+
let username;
|
|
77
|
+
let password;
|
|
78
|
+
if (!username || !password) {
|
|
79
|
+
const credentials = await (0, credentialsUtils_1.promptCredentials)(this.ipAddress);
|
|
80
|
+
username = credentials.username;
|
|
81
|
+
password = credentials.password;
|
|
82
|
+
}
|
|
83
|
+
const uploadDetails = await this.fetchUploadDetails(username, password);
|
|
84
|
+
if (!uploadDetails) {
|
|
85
|
+
throw new Error("Failed to retrieve upload details.");
|
|
86
|
+
}
|
|
87
|
+
return { ...uploadDetails, username, password };
|
|
88
|
+
}
|
|
89
|
+
// Method to send a POST request
|
|
90
|
+
async postRequest(url, data) {
|
|
91
|
+
return new Promise((resolve, reject) => {
|
|
92
|
+
const urlObj = new url_1.URL(url);
|
|
93
|
+
const options = {
|
|
94
|
+
hostname: urlObj.hostname,
|
|
95
|
+
port: urlObj.port || PropagationServer.port,
|
|
96
|
+
path: urlObj.pathname,
|
|
97
|
+
method: "POST",
|
|
98
|
+
headers: {
|
|
99
|
+
"Content-Type": "application/json",
|
|
100
|
+
"Content-Length": Buffer.byteLength(data),
|
|
101
|
+
},
|
|
102
|
+
key: fs_1.default.readFileSync(PropagationServer.keyPath),
|
|
103
|
+
cert: fs_1.default.readFileSync(PropagationServer.certPath),
|
|
104
|
+
rejectUnauthorized: false,
|
|
105
|
+
};
|
|
106
|
+
const req = https_1.default.request(options, (res) => {
|
|
107
|
+
if (res.statusCode === 200) {
|
|
108
|
+
resolve();
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
reject(new Error(`POST request failed with status ${res.statusCode}: ${res.statusMessage}`));
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
req.on("error", (err) => {
|
|
115
|
+
reject(err);
|
|
116
|
+
});
|
|
117
|
+
req.write(data);
|
|
118
|
+
req.end();
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
// Method to fetch upload details from the server
|
|
122
|
+
// Method to fetch upload details from the server
|
|
123
|
+
async fetchUploadDetails(username, password) {
|
|
124
|
+
const remote = `https://${this.ipAddress}:${PropagationServer.port}/${this.storeId}`;
|
|
125
|
+
return (0, spinnerUtils_1.waitForPromise)(() => {
|
|
126
|
+
return new Promise((resolve, reject) => {
|
|
127
|
+
const url = new url_1.URL(remote);
|
|
128
|
+
const options = {
|
|
129
|
+
hostname: url.hostname,
|
|
130
|
+
port: url.port,
|
|
131
|
+
path: url.pathname,
|
|
132
|
+
method: "HEAD",
|
|
133
|
+
headers: {
|
|
134
|
+
Authorization: `Basic ${Buffer.from(`${username}:${password}`).toString("base64")}`,
|
|
135
|
+
},
|
|
136
|
+
key: fs_1.default.readFileSync(PropagationServer.keyPath),
|
|
137
|
+
cert: fs_1.default.readFileSync(PropagationServer.certPath),
|
|
138
|
+
rejectUnauthorized: false, // Allow self-signed certificates
|
|
139
|
+
};
|
|
140
|
+
const req = https_1.default.request(options, (res) => {
|
|
141
|
+
if (res.statusCode === 200) {
|
|
142
|
+
// Check if the headers are present and valid
|
|
143
|
+
const nonce = res.headers["x-nonce"];
|
|
144
|
+
const lastUploadedHash = res.headers?.["x-last-uploaded-hash"] ||
|
|
145
|
+
"0000000000000000000000000000000000000000000000000000000000000000";
|
|
146
|
+
const generationIndex = res.headers?.["x-generation-index"] || 0;
|
|
147
|
+
console.log({ nonce, lastUploadedHash, generationIndex });
|
|
148
|
+
if (nonce) {
|
|
149
|
+
resolve({
|
|
150
|
+
nonce: nonce,
|
|
151
|
+
lastUploadedHash: lastUploadedHash,
|
|
152
|
+
generationIndex: Number(generationIndex),
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
reject(new Error("Missing required headers in the response."));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
reject(new Error(`Failed to perform preflight check: ${res.statusCode} ${res.statusMessage}`));
|
|
161
|
+
}
|
|
162
|
+
});
|
|
163
|
+
req.on("error", (err) => {
|
|
164
|
+
console.error(err.message);
|
|
165
|
+
resolve(false); // Resolve to false if there is an error
|
|
166
|
+
});
|
|
167
|
+
req.end();
|
|
168
|
+
});
|
|
169
|
+
}, "Performing remote preflight", "Preflight succeeded.", "Error on preflight.");
|
|
170
|
+
}
|
|
171
|
+
// Core method to upload a file directly to the server using a stream
|
|
172
|
+
async uploadFileDirect(filePath, uploadUrl, username, password, keyOwnershipSig, publicKey, nonce) {
|
|
173
|
+
const fileStream = fs_1.default.createReadStream(filePath);
|
|
174
|
+
const fileSize = fs_1.default.statSync(filePath).size;
|
|
175
|
+
return new Promise((resolve, reject) => {
|
|
176
|
+
const url = new url_1.URL(uploadUrl);
|
|
177
|
+
const options = {
|
|
178
|
+
hostname: url.hostname,
|
|
179
|
+
port: url.port,
|
|
180
|
+
path: url.pathname,
|
|
181
|
+
method: "PUT",
|
|
182
|
+
headers: {
|
|
183
|
+
"Content-Type": "application/octet-stream",
|
|
184
|
+
"Content-Length": fileSize,
|
|
185
|
+
Authorization: `Basic ${Buffer.from(`${username}:${password}`).toString("base64")}`,
|
|
186
|
+
"x-key-ownership-sig": keyOwnershipSig,
|
|
187
|
+
"x-public-key": publicKey,
|
|
188
|
+
"x-nonce": nonce,
|
|
189
|
+
},
|
|
190
|
+
key: fs_1.default.readFileSync(PropagationServer.keyPath),
|
|
191
|
+
cert: fs_1.default.readFileSync(PropagationServer.certPath),
|
|
192
|
+
rejectUnauthorized: false,
|
|
193
|
+
};
|
|
194
|
+
const req = https_1.default.request(options, (res) => {
|
|
195
|
+
if (res.statusCode === 200) {
|
|
196
|
+
resolve();
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
reject(new Error(`Upload failed with status ${res.statusCode}: ${res.statusMessage}`));
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
req.on("error", (err) => {
|
|
203
|
+
reject(err);
|
|
204
|
+
});
|
|
205
|
+
fileStream.pipe(req);
|
|
206
|
+
fileStream.on("error", (err) => {
|
|
207
|
+
reject(err);
|
|
208
|
+
});
|
|
209
|
+
req.on("end", () => {
|
|
210
|
+
resolve();
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
// Generic retry operation handler to reduce redundancy
|
|
215
|
+
async retryOperation(operation, errorMessage) {
|
|
216
|
+
let attempt = 0;
|
|
217
|
+
let delay = PropagationServer.initialDelay;
|
|
218
|
+
while (attempt < PropagationServer.maxRetries) {
|
|
219
|
+
try {
|
|
220
|
+
return await operation();
|
|
221
|
+
}
|
|
222
|
+
catch (error) {
|
|
223
|
+
if (attempt < PropagationServer.maxRetries - 1) {
|
|
224
|
+
console.warn(`Attempt ${attempt + 1} failed: ${error.message}. Retrying in ${delay / 1000} seconds...`);
|
|
225
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
226
|
+
delay = Math.min(PropagationServer.maxDelay, delay * PropagationServer.delayMultiplier);
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
console.error(`${errorMessage}. Aborting.`);
|
|
230
|
+
throw error;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
attempt++;
|
|
234
|
+
}
|
|
235
|
+
throw new Error(errorMessage);
|
|
236
|
+
}
|
|
237
|
+
// Core method to fetch content from a URL
|
|
238
|
+
async fetch(url) {
|
|
239
|
+
return new Promise((resolve, reject) => {
|
|
240
|
+
const urlObj = new url_1.URL(url);
|
|
241
|
+
const options = {
|
|
242
|
+
hostname: urlObj.hostname,
|
|
243
|
+
port: urlObj.port,
|
|
244
|
+
path: urlObj.pathname + urlObj.search,
|
|
245
|
+
method: "GET",
|
|
246
|
+
key: fs_1.default.readFileSync(PropagationServer.keyPath),
|
|
247
|
+
cert: fs_1.default.readFileSync(PropagationServer.certPath),
|
|
248
|
+
rejectUnauthorized: false,
|
|
249
|
+
};
|
|
250
|
+
const request = https_1.default.request(options, (response) => {
|
|
251
|
+
let data = "";
|
|
252
|
+
if (response.statusCode === 200) {
|
|
253
|
+
response.on("data", (chunk) => {
|
|
254
|
+
data += chunk;
|
|
255
|
+
});
|
|
256
|
+
response.on("end", () => {
|
|
257
|
+
resolve(data);
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
else if (response.statusCode === 301 || response.statusCode === 302) {
|
|
261
|
+
const redirectUrl = response.headers.location;
|
|
262
|
+
if (redirectUrl) {
|
|
263
|
+
this.fetch(redirectUrl).then(resolve).catch(reject);
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
reject(new Error("Redirected without a location header"));
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
reject(new Error(`Failed to retrieve data from ${url}. Status code: ${response.statusCode}`));
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
request.on("error", (error) => {
|
|
274
|
+
console.error(`Request error for ${url}:`, error);
|
|
275
|
+
reject(error);
|
|
276
|
+
});
|
|
277
|
+
request.end();
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
// Helper method to perform HEAD requests
|
|
281
|
+
async head(url) {
|
|
282
|
+
return new Promise((resolve, reject) => {
|
|
283
|
+
const urlObj = new url_1.URL(url);
|
|
284
|
+
const options = {
|
|
285
|
+
hostname: urlObj.hostname,
|
|
286
|
+
port: urlObj.port || PropagationServer.port,
|
|
287
|
+
path: urlObj.pathname + urlObj.search,
|
|
288
|
+
method: "HEAD",
|
|
289
|
+
key: fs_1.default.readFileSync(PropagationServer.keyPath),
|
|
290
|
+
cert: fs_1.default.readFileSync(PropagationServer.certPath),
|
|
291
|
+
rejectUnauthorized: false,
|
|
292
|
+
};
|
|
293
|
+
const request = https_1.default.request(options, (response) => {
|
|
294
|
+
if (response.statusCode === 200) {
|
|
295
|
+
resolve(true);
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
resolve(false);
|
|
299
|
+
}
|
|
300
|
+
});
|
|
301
|
+
request.on("error", (error) => {
|
|
302
|
+
console.error(`Request error for ${url}:`, error);
|
|
303
|
+
reject(false);
|
|
304
|
+
});
|
|
305
|
+
request.end();
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
// Helper method to fetch JSON data from a URL
|
|
309
|
+
async fetchJson(url) {
|
|
310
|
+
const response = await this.fetch(url);
|
|
311
|
+
return JSON.parse(response);
|
|
312
|
+
}
|
|
313
|
+
// Helper method to fetch content with retries and redirection handling
|
|
314
|
+
/*private async fetchWithRetries(url: string): Promise<string> {
|
|
315
|
+
let attempt = 0;
|
|
316
|
+
const maxRetries = 5;
|
|
317
|
+
const initialDelay = 2000; // 2 seconds
|
|
318
|
+
const maxDelay = 10000; // 10 seconds
|
|
319
|
+
const delayMultiplier = 1.5;
|
|
320
|
+
let delay = initialDelay;
|
|
321
|
+
|
|
322
|
+
while (attempt < maxRetries) {
|
|
323
|
+
try {
|
|
324
|
+
return await this.fetch(url);
|
|
325
|
+
} catch (error: any) {
|
|
326
|
+
if (attempt < maxRetries - 1) {
|
|
327
|
+
console.warn(
|
|
328
|
+
`Attempt ${attempt + 1} failed: ${error.message}. Retrying in ${
|
|
329
|
+
delay / 1000
|
|
330
|
+
} seconds...`
|
|
331
|
+
);
|
|
332
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
333
|
+
delay = Math.min(maxDelay, delay * delayMultiplier);
|
|
334
|
+
} else {
|
|
335
|
+
console.error(`Failed to retrieve data from ${url}. Aborting.`);
|
|
336
|
+
throw new Error(`Failed to retrieve data: ${error.message}`);
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
attempt++;
|
|
340
|
+
}
|
|
341
|
+
throw new Error(
|
|
342
|
+
`Failed to retrieve data from ${url} after ${maxRetries} attempts.`
|
|
343
|
+
);
|
|
344
|
+
}*/
|
|
345
|
+
// Helper method to create a stream with retry logic
|
|
346
|
+
async createReadStreamWithRetries(url) {
|
|
347
|
+
let attempt = 0;
|
|
348
|
+
const maxRetries = 1;
|
|
349
|
+
const initialDelay = PropagationServer.initialDelay;
|
|
350
|
+
const maxDelay = PropagationServer.maxDelay;
|
|
351
|
+
const delayMultiplier = PropagationServer.delayMultiplier;
|
|
352
|
+
let delay = initialDelay;
|
|
353
|
+
while (attempt < maxRetries) {
|
|
354
|
+
try {
|
|
355
|
+
return await this.createReadStream(url); // Stream data chunk by chunk
|
|
356
|
+
}
|
|
357
|
+
catch (error) {
|
|
358
|
+
if (attempt < maxRetries - 1) {
|
|
359
|
+
console.warn(`Attempt ${attempt + 1} failed: ${error.message}. Retrying in ${delay / 1000} seconds...`);
|
|
360
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
|
361
|
+
delay = Math.min(maxDelay, delay * delayMultiplier);
|
|
362
|
+
}
|
|
363
|
+
else {
|
|
364
|
+
console.error(`Failed to create stream from ${url}. Aborting.`);
|
|
365
|
+
throw new Error(`Failed to create stream: ${error.message}`);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
attempt++;
|
|
369
|
+
}
|
|
370
|
+
throw new Error(`Failed to create stream from ${url} after ${maxRetries} attempts.`);
|
|
371
|
+
}
|
|
372
|
+
// Helper method to fetch a readable stream from a URL
|
|
373
|
+
async createReadStream(url) {
|
|
374
|
+
return new Promise((resolve, reject) => {
|
|
375
|
+
const urlObj = new url_1.URL(url);
|
|
376
|
+
const options = {
|
|
377
|
+
hostname: urlObj.hostname,
|
|
378
|
+
port: urlObj.port || PropagationServer.port,
|
|
379
|
+
path: urlObj.pathname + urlObj.search,
|
|
380
|
+
method: "GET",
|
|
381
|
+
key: fs_1.default.readFileSync(PropagationServer.keyPath),
|
|
382
|
+
cert: fs_1.default.readFileSync(PropagationServer.certPath),
|
|
383
|
+
rejectUnauthorized: false,
|
|
384
|
+
};
|
|
385
|
+
const request = https_1.default.request(options, (response) => {
|
|
386
|
+
if (response.statusCode === 200) {
|
|
387
|
+
resolve(response); // Return the response stream chunk by chunk
|
|
388
|
+
}
|
|
389
|
+
else if (response.statusCode === 301 || response.statusCode === 302) {
|
|
390
|
+
const redirectUrl = response.headers.location;
|
|
391
|
+
if (redirectUrl) {
|
|
392
|
+
this.createReadStream(redirectUrl).then(resolve).catch(reject);
|
|
393
|
+
}
|
|
394
|
+
else {
|
|
395
|
+
reject(new Error("Redirected without a location header"));
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
else {
|
|
399
|
+
reject(new Error(`Failed to retrieve stream from ${url}. Status code: ${response.statusCode}`));
|
|
400
|
+
}
|
|
401
|
+
});
|
|
402
|
+
request.on("error", (error) => {
|
|
403
|
+
console.error(`Request error for ${url}:`, error);
|
|
404
|
+
reject(error);
|
|
405
|
+
});
|
|
406
|
+
request.end();
|
|
407
|
+
});
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
exports.PropagationServer = PropagationServer;
|
|
411
|
+
PropagationServer.port = 4159;
|
|
412
|
+
PropagationServer.maxRetries = 5;
|
|
413
|
+
PropagationServer.initialDelay = 2000; // 2 seconds
|
|
414
|
+
PropagationServer.maxDelay = 10000; // 10 seconds
|
|
415
|
+
PropagationServer.delayMultiplier = 1.5;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/DigNetwork/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./DigPeer"), exports);
|
|
18
|
+
__exportStar(require("./DigNetwork"), exports);
|
|
19
|
+
__exportStar(require("./DigChallenge"), exports);
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { DataStore as DataStoreDriver, DataStoreMetadata } from "datalayer-driver";
|
|
2
|
+
import { RootHistoryItem } from "../types";
|
|
3
|
+
import { DataIntegrityTree, DataIntegrityTreeOptions } from "../DataIntegrityTree";
|
|
4
|
+
import { CreateStoreUserInputs } from "../types";
|
|
5
|
+
export declare class DataStore {
|
|
6
|
+
private storeId;
|
|
7
|
+
private tree;
|
|
8
|
+
constructor(storeId: string, options?: DataIntegrityTreeOptions);
|
|
9
|
+
get StoreId(): string;
|
|
10
|
+
get Tree(): DataIntegrityTree;
|
|
11
|
+
toBuffer(): Buffer;
|
|
12
|
+
toString(): string;
|
|
13
|
+
serialize(): string;
|
|
14
|
+
static getActiveStore(): Promise<DataStore | undefined>;
|
|
15
|
+
static deserialize(serialized: string): DataStore;
|
|
16
|
+
static from(storeId: string | Buffer): DataStore;
|
|
17
|
+
static create(inputs?: CreateStoreUserInputs): Promise<DataStore>;
|
|
18
|
+
private static mint;
|
|
19
|
+
/**
|
|
20
|
+
* Instance method to calculate the disk space used by the store/storeId folder.
|
|
21
|
+
* @returns {Promise<number>} - The total disk space used by the store in bytes.
|
|
22
|
+
*/
|
|
23
|
+
getDiskSpace(): Promise<bigint>;
|
|
24
|
+
/**
|
|
25
|
+
* Static method to calculate the total disk space used by all stores in the store folder.
|
|
26
|
+
* @returns {Promise<number>} - The total disk space used by the store folder in bytes.
|
|
27
|
+
*/
|
|
28
|
+
static getTotalDiskSpace(): Promise<bigint>;
|
|
29
|
+
/**
|
|
30
|
+
* Helper method to calculate the size of a folder and its subfolders recursively.
|
|
31
|
+
* @param folderPath - The path of the folder to calculate the size of.
|
|
32
|
+
* @returns {Promise<number>} - The total size of the folder in bytes.
|
|
33
|
+
*/
|
|
34
|
+
private static calculateFolderSize;
|
|
35
|
+
static getAllStores(): DataStore[];
|
|
36
|
+
fetchCoinInfo(): Promise<{
|
|
37
|
+
latestStore: DataStoreDriver;
|
|
38
|
+
latestHeight: number;
|
|
39
|
+
latestHash: Buffer;
|
|
40
|
+
}>;
|
|
41
|
+
getCreationHeight(): Promise<{
|
|
42
|
+
createdAtHeight: number;
|
|
43
|
+
createdAtHash: Buffer;
|
|
44
|
+
}>;
|
|
45
|
+
private setCreationHeight;
|
|
46
|
+
getRootHistory(): Promise<RootHistoryItem[]>;
|
|
47
|
+
getLocalRootHistory(): Promise<RootHistoryItem[] | undefined>;
|
|
48
|
+
validate(): Promise<boolean>;
|
|
49
|
+
getMetaData(): Promise<DataStoreMetadata>;
|
|
50
|
+
isSynced(): Promise<boolean>;
|
|
51
|
+
hasMetaWritePermissions(publicSyntheticKey?: Buffer): Promise<boolean>;
|
|
52
|
+
updateMetadata(metadata: DataStoreMetadata): Promise<DataStoreDriver>;
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=DataStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DataStore.d.ts","sourceRoot":"","sources":["../../src/blockchain/DataStore.ts"],"names":[],"mappings":"AAEA,OAAO,EAOL,SAAS,IAAI,eAAe,EAE5B,iBAAiB,EAIlB,MAAM,kBAAkB,CAAC;AAY1B,OAAO,EAAE,eAAe,EAAW,MAAM,UAAU,CAAC;AAGpD,OAAO,EACL,iBAAiB,EACjB,wBAAwB,EACzB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AASjD,qBAAa,SAAS;IACpB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,IAAI,CAAoB;gBAEpB,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,wBAAwB;IAiB/D,IAAW,OAAO,IAAI,MAAM,CAE3B;IAED,IAAW,IAAI,IAAI,iBAAiB,CAEnC;IAEM,QAAQ,IAAI,MAAM;IAIlB,QAAQ,IAAI,MAAM;IAIlB,SAAS,IAAI,MAAM;WAMN,cAAc,IAAI,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;WAOtD,WAAW,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS;WAK1C,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;WAYnC,MAAM,CACxB,MAAM,GAAE,qBAA0B,GACjC,OAAO,CAAC,SAAS,CAAC;mBAyCA,IAAI;IA4FzB;;;OAGG;IACU,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC;IAK5C;;;OAGG;WACiB,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC;IAIxD;;;;OAIG;mBACkB,mBAAmB;WAqB1B,YAAY,IAAI,SAAS,EAAE;IAW5B,aAAa,IAAI,OAAO,CAAC;QACpC,WAAW,EAAE,eAAe,CAAC;QAC7B,YAAY,EAAE,MAAM,CAAC;QACrB,UAAU,EAAE,MAAM,CAAC;KACpB,CAAC;IAyGW,iBAAiB,IAAI,OAAO,CAAC;QACxC,eAAe,EAAE,MAAM,CAAC;QACxB,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC;YA0BY,iBAAiB;IAYlB,cAAc,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;IAsB5C,mBAAmB,IAAI,OAAO,CAAC,eAAe,EAAE,GAAG,SAAS,CAAC;IAiB7D,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC;IA+E5B,WAAW,IAAI,OAAO,CAAC,iBAAiB,CAAC;IAKzC,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC;IAgB5B,uBAAuB,CAClC,kBAAkB,CAAC,EAAE,MAAM,GAC1B,OAAO,CAAC,OAAO,CAAC;IAkBN,cAAc,CACzB,QAAQ,EAAE,iBAAiB,GAC1B,OAAO,CAAC,eAAe,CAAC;CA8C5B"}
|