@dignetwork/dig-sdk 0.0.1-alpha.2 → 0.0.1-alpha.21
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/DataIntegrityTree/DataIntegrityTree.d.ts +1 -1
- package/dist/DataIntegrityTree/DataIntegrityTree.d.ts.map +1 -1
- package/dist/DataIntegrityTree/DataIntegrityTree.js +29 -5
- package/dist/DigNetwork/ContentServer.d.ts +5 -1
- package/dist/DigNetwork/ContentServer.d.ts.map +1 -1
- package/dist/DigNetwork/ContentServer.js +26 -11
- package/dist/DigNetwork/DigNetwork.d.ts +3 -1
- package/dist/DigNetwork/DigNetwork.d.ts.map +1 -1
- package/dist/DigNetwork/DigNetwork.js +79 -9
- package/dist/blockchain/DataStore.d.ts +2 -0
- package/dist/blockchain/DataStore.d.ts.map +1 -1
- package/dist/blockchain/DataStore.js +23 -0
- package/dist/blockchain/FullNodePeer.d.ts +7 -0
- package/dist/blockchain/FullNodePeer.d.ts.map +1 -1
- package/dist/blockchain/FullNodePeer.js +38 -6
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +4 -9
- package/dist/utils/directoryUtils.d.ts +0 -6
- package/dist/utils/directoryUtils.d.ts.map +1 -1
- package/dist/utils/directoryUtils.js +30 -11
- package/package.json +2 -1
|
@@ -106,7 +106,7 @@ declare class DataIntegrityTree {
|
|
|
106
106
|
* @param rootHash - The root hash of the tree. Defaults to the latest root hash.
|
|
107
107
|
* @returns The readable stream for the file.
|
|
108
108
|
*/
|
|
109
|
-
getValueStream(hexKey: string, rootHash?: string | null): Readable;
|
|
109
|
+
getValueStream(hexKey: string, rootHash?: string | null, byteOffset?: number | null, length?: number | null): Readable;
|
|
110
110
|
/**
|
|
111
111
|
* Delete all leaves from the Merkle tree.
|
|
112
112
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataIntegrityTree.d.ts","sourceRoot":"","sources":["../../src/DataIntegrityTree/DataIntegrityTree.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AAuClC,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAGlB,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;GAEG;AACH,cAAM,iBAAiB;IACrB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,OAAO,CAAS;IACjB,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC5D,OAAO,CAAC,IAAI,CAAa;gBAEb,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,wBAA6B;WAiDrD,IAAI,
|
|
1
|
+
{"version":3,"file":"DataIntegrityTree.d.ts","sourceRoot":"","sources":["../../src/DataIntegrityTree/DataIntegrityTree.ts"],"names":[],"mappings":"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"}
|
|
@@ -111,7 +111,10 @@ class DataIntegrityTree {
|
|
|
111
111
|
}
|
|
112
112
|
}
|
|
113
113
|
static from(storeId, options) {
|
|
114
|
-
return new DataIntegrityTree(storeId, {
|
|
114
|
+
return new DataIntegrityTree(storeId, {
|
|
115
|
+
...options,
|
|
116
|
+
disableInitialize: true,
|
|
117
|
+
});
|
|
115
118
|
}
|
|
116
119
|
/**
|
|
117
120
|
* Load the manifest file.
|
|
@@ -220,14 +223,19 @@ class DataIntegrityTree {
|
|
|
220
223
|
hash: combinedHash,
|
|
221
224
|
sha256: sha256,
|
|
222
225
|
});
|
|
226
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
223
227
|
this._rebuildTree();
|
|
228
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
224
229
|
resolve();
|
|
225
230
|
}
|
|
226
231
|
catch (err) {
|
|
227
232
|
reject(err);
|
|
228
233
|
}
|
|
234
|
+
tempWriteStream.end();
|
|
235
|
+
finalWriteStream.end();
|
|
229
236
|
});
|
|
230
237
|
tempWriteStream.on("error", (err) => {
|
|
238
|
+
tempWriteStream.end();
|
|
231
239
|
reject(err);
|
|
232
240
|
});
|
|
233
241
|
readStream.on("error", (err) => {
|
|
@@ -337,7 +345,9 @@ class DataIntegrityTree {
|
|
|
337
345
|
? fs.readFileSync(manifestPath, "utf-8").trim().split("\n")
|
|
338
346
|
: [];
|
|
339
347
|
// Check if the last entry is the same as the rootHash to avoid duplicates
|
|
340
|
-
const latestRootHash = manifestContent.length > 0
|
|
348
|
+
const latestRootHash = manifestContent.length > 0
|
|
349
|
+
? manifestContent[manifestContent.length - 1]
|
|
350
|
+
: null;
|
|
341
351
|
if (latestRootHash !== rootHash) {
|
|
342
352
|
// Append the new rootHash if it is not the same as the last one
|
|
343
353
|
fs.appendFileSync(manifestPath, `${rootHash}\n`);
|
|
@@ -413,7 +423,7 @@ class DataIntegrityTree {
|
|
|
413
423
|
* @param rootHash - The root hash of the tree. Defaults to the latest root hash.
|
|
414
424
|
* @returns The readable stream for the file.
|
|
415
425
|
*/
|
|
416
|
-
getValueStream(hexKey, rootHash = null) {
|
|
426
|
+
getValueStream(hexKey, rootHash = null, byteOffset = null, length = null) {
|
|
417
427
|
if (!isHexString(hexKey)) {
|
|
418
428
|
throw new Error("key must be a valid hex string");
|
|
419
429
|
}
|
|
@@ -436,8 +446,22 @@ class DataIntegrityTree {
|
|
|
436
446
|
if (!fs.existsSync(filePath)) {
|
|
437
447
|
throw new Error(`File at path ${filePath} does not exist`);
|
|
438
448
|
}
|
|
439
|
-
|
|
440
|
-
|
|
449
|
+
const fileSize = fs.statSync(filePath).size;
|
|
450
|
+
// Validate offset and length
|
|
451
|
+
if (byteOffset !== null && length !== null) {
|
|
452
|
+
if (byteOffset + length > fileSize) {
|
|
453
|
+
throw new Error(`Offset (${byteOffset}) and length (${length}) exceed the file size (${fileSize}).`);
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
// Create the read stream with optional byte range
|
|
457
|
+
const options = {};
|
|
458
|
+
if (byteOffset !== null) {
|
|
459
|
+
options.start = byteOffset;
|
|
460
|
+
}
|
|
461
|
+
if (length !== null && byteOffset !== null) {
|
|
462
|
+
options.end = byteOffset + length - 1; // `end` is inclusive, hence `byteOffset + length - 1`
|
|
463
|
+
}
|
|
464
|
+
const readStream = fs.createReadStream(filePath, options);
|
|
441
465
|
const decompressStream = zlib.createGunzip();
|
|
442
466
|
// Return the combined stream as a generic Readable stream
|
|
443
467
|
return readStream.pipe(decompressStream);
|
|
@@ -3,6 +3,8 @@ import { Readable } from "stream";
|
|
|
3
3
|
export declare class ContentServer {
|
|
4
4
|
private ipAddress;
|
|
5
5
|
private storeId;
|
|
6
|
+
private static certPath;
|
|
7
|
+
private static keyPath;
|
|
6
8
|
private static readonly port;
|
|
7
9
|
constructor(ipAddress: string, storeId: string);
|
|
8
10
|
getKey(key: string, rootHash: string, challengeHex?: string): Promise<string>;
|
|
@@ -15,7 +17,9 @@ export declare class ContentServer {
|
|
|
15
17
|
success: boolean;
|
|
16
18
|
headers?: http.IncomingHttpHeaders;
|
|
17
19
|
}>;
|
|
18
|
-
headStore(
|
|
20
|
+
headStore(options?: {
|
|
21
|
+
hasRootHash: string;
|
|
22
|
+
}): Promise<{
|
|
19
23
|
success: boolean;
|
|
20
24
|
headers?: http.IncomingHttpHeaders;
|
|
21
25
|
}>;
|
|
@@ -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;AAGlC,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,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAa7E,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC;IAepC,YAAY,IAAI,OAAO,CAAC,GAAG,CAAC;IAM5B,cAAc,IAAI,OAAO,CAAC,GAAG,CAAC;IAM9B,cAAc,IAAI,OAAO,CAAC,GAAG,CAAC;IAM9B,YAAY,IAAI,OAAO,CAAC,GAAG,CAAC;IAM5B,OAAO,CAClB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,IAAI,CAAC,mBAAmB,CAAA;KAAE,CAAC;IAMvD,SAAS,CAAC,OAAO,CAAC,EAAE;QAAE,WAAW,EAAE,MAAM,CAAA;KAAC,GAAG,OAAO,CAAC;QAChE,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,CAAC,EAAE,IAAI,CAAC,mBAAmB,CAAC;KACpC,CAAC;IAUK,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;YA0ClC,IAAI;YA0EJ,SAAS;YAMT,gBAAgB;YAiChB,KAAK;CA0DpB"}
|
|
@@ -4,17 +4,24 @@ 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 fs_1 = __importDefault(require("fs"));
|
|
7
8
|
const http_1 = __importDefault(require("http"));
|
|
8
9
|
const url_1 = require("url");
|
|
10
|
+
const ssl_1 = require("../utils/ssl");
|
|
9
11
|
class ContentServer {
|
|
10
12
|
constructor(ipAddress, storeId) {
|
|
11
13
|
this.ipAddress = ipAddress;
|
|
12
14
|
this.storeId = storeId;
|
|
15
|
+
if (!ContentServer.certPath || !ContentServer.keyPath) {
|
|
16
|
+
const { certPath, keyPath } = (0, ssl_1.getOrCreateSSLCerts)();
|
|
17
|
+
ContentServer.certPath = certPath;
|
|
18
|
+
ContentServer.keyPath = keyPath;
|
|
19
|
+
}
|
|
13
20
|
}
|
|
14
21
|
// Method to get the content of a specified key from the peer, with optional challenge query
|
|
15
22
|
async getKey(key, rootHash, challengeHex) {
|
|
16
23
|
// Construct the base URL
|
|
17
|
-
let url = `
|
|
24
|
+
let url = `https://${this.ipAddress}/chia.${this.storeId}.${rootHash}/${key}`;
|
|
18
25
|
// If a challenge is provided, append it as a query parameter
|
|
19
26
|
if (challengeHex) {
|
|
20
27
|
url += `?challenge=${challengeHex}`;
|
|
@@ -35,38 +42,40 @@ class ContentServer {
|
|
|
35
42
|
}
|
|
36
43
|
// Method to get the .well-known information
|
|
37
44
|
async getWellKnown() {
|
|
38
|
-
const url = `
|
|
45
|
+
const url = `https://${this.ipAddress}/.well-known`;
|
|
39
46
|
return this.fetchJson(url);
|
|
40
47
|
}
|
|
41
48
|
// Method to get the list of known stores
|
|
42
49
|
async getKnownStores() {
|
|
43
|
-
const url = `
|
|
50
|
+
const url = `https://${this.ipAddress}/.well-known/stores`;
|
|
44
51
|
return this.fetchJson(url);
|
|
45
52
|
}
|
|
46
53
|
// Method to get the index of all stores
|
|
47
54
|
async getStoresIndex() {
|
|
48
|
-
const url = `
|
|
55
|
+
const url = `https://${this.ipAddress}/`;
|
|
49
56
|
return this.fetchJson(url);
|
|
50
57
|
}
|
|
51
58
|
// Method to get the index of keys in a store
|
|
52
59
|
async getKeysIndex() {
|
|
53
|
-
const url = `
|
|
60
|
+
const url = `https://${this.ipAddress}/${this.storeId}`;
|
|
54
61
|
return this.fetchJson(url);
|
|
55
62
|
}
|
|
56
63
|
// Method to check if a specific key exists (HEAD request)
|
|
57
64
|
async headKey(key) {
|
|
58
|
-
const url = `
|
|
65
|
+
const url = `https://${this.ipAddress}/${this.storeId}/${key}`;
|
|
59
66
|
return this.head(url); // Return the object from head method
|
|
60
67
|
}
|
|
61
68
|
// Method to check if a specific store exists (HEAD request)
|
|
62
|
-
async headStore() {
|
|
63
|
-
|
|
64
|
-
|
|
69
|
+
async headStore(options) {
|
|
70
|
+
let url = `https://${this.ipAddress}/${this.storeId}`;
|
|
71
|
+
if (options?.hasRootHash) {
|
|
72
|
+
url += `hasRootHash=${options.hasRootHash}`;
|
|
73
|
+
}
|
|
65
74
|
return this.head(url); // Return the object from head method
|
|
66
75
|
}
|
|
67
76
|
streamKey(key) {
|
|
68
77
|
return new Promise((resolve, reject) => {
|
|
69
|
-
const url = `
|
|
78
|
+
const url = `https://${this.ipAddress}/${this.storeId}/${key}`;
|
|
70
79
|
const urlObj = new url_1.URL(url);
|
|
71
80
|
const requestOptions = {
|
|
72
81
|
hostname: urlObj.hostname,
|
|
@@ -111,6 +120,9 @@ class ContentServer {
|
|
|
111
120
|
(urlObj.protocol === "http:" ? 80 : ContentServer.port),
|
|
112
121
|
path: urlObj.pathname + urlObj.search,
|
|
113
122
|
method: "HEAD",
|
|
123
|
+
key: fs_1.default.readFileSync(ContentServer.keyPath),
|
|
124
|
+
cert: fs_1.default.readFileSync(ContentServer.certPath),
|
|
125
|
+
rejectUnauthorized: false,
|
|
114
126
|
};
|
|
115
127
|
const request = http_1.default.request(requestOptions, (response) => {
|
|
116
128
|
const { statusCode, headers } = response;
|
|
@@ -201,6 +213,9 @@ class ContentServer {
|
|
|
201
213
|
port: urlObj.port || ContentServer.port,
|
|
202
214
|
path: urlObj.pathname + urlObj.search, // Include query params
|
|
203
215
|
method: "GET",
|
|
216
|
+
key: fs_1.default.readFileSync(ContentServer.keyPath),
|
|
217
|
+
cert: fs_1.default.readFileSync(ContentServer.certPath),
|
|
218
|
+
rejectUnauthorized: false,
|
|
204
219
|
};
|
|
205
220
|
const request = http_1.default.request(requestOptions, (response) => {
|
|
206
221
|
let data = "";
|
|
@@ -240,4 +255,4 @@ class ContentServer {
|
|
|
240
255
|
}
|
|
241
256
|
}
|
|
242
257
|
exports.ContentServer = ContentServer;
|
|
243
|
-
ContentServer.port =
|
|
258
|
+
ContentServer.port = 4161;
|
|
@@ -6,10 +6,12 @@ export declare class DigNetwork {
|
|
|
6
6
|
private peerBlacklist;
|
|
7
7
|
constructor(storeId: string);
|
|
8
8
|
private uploadPreflight;
|
|
9
|
+
uploadStoreHead(digPeer: DigPeer): Promise<void>;
|
|
9
10
|
uploadStore(digPeer: DigPeer): Promise<void>;
|
|
10
11
|
static subscribeToStore(storeId: string): Promise<void>;
|
|
12
|
+
static findPeerWithStoreKey(storeId: string, rootHash: string, key?: string): Promise<string | null>;
|
|
11
13
|
static unsubscribeFromStore(storeId: string): void;
|
|
12
|
-
downloadFiles(forceDownload?: boolean, renderProgressBar?: boolean): Promise<void>;
|
|
14
|
+
downloadFiles(forceDownload?: boolean, renderProgressBar?: boolean, skipData?: boolean): Promise<void>;
|
|
13
15
|
private fetchAvailablePeers;
|
|
14
16
|
private downloadHeightFile;
|
|
15
17
|
private downloadManifestFile;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DigNetwork.d.ts","sourceRoot":"","sources":["../../src/DigNetwork/DigNetwork.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,qBAAa,UAAU;IACrB,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,aAAa,CAA2B;gBAEpC,OAAO,EAAE,MAAM;YAOb,eAAe;
|
|
1
|
+
{"version":3,"file":"DigNetwork.d.ts","sourceRoot":"","sources":["../../src/DigNetwork/DigNetwork.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,qBAAa,UAAU;IACrB,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,aAAa,CAA2B;gBAEpC,OAAO,EAAE,MAAM;YAOb,eAAe;IA8ChB,eAAe,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAsDhD,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;WA6BrC,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;WAQhD,oBAAoB,CACtC,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,EAChB,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;WA2CX,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAQ5C,aAAa,CACxB,aAAa,GAAE,OAAe,EAC9B,iBAAiB,GAAE,OAAc,EACjC,QAAQ,GAAE,OAAe,GACxB,OAAO,CAAC,IAAI,CAAC;YAqFF,mBAAmB;YAWnB,kBAAkB;YASlB,oBAAoB;YASpB,qBAAqB;YAuErB,cAAc;CAoB7B"}
|
|
@@ -63,18 +63,50 @@ class DigNetwork {
|
|
|
63
63
|
}
|
|
64
64
|
return { generationIndex, lastLocalRootHash };
|
|
65
65
|
}
|
|
66
|
+
async uploadStoreHead(digPeer) {
|
|
67
|
+
// First make sure that the remote store is up to date.
|
|
68
|
+
const rootHistory = await this.dataStore.getRootHistory();
|
|
69
|
+
const localManifestHashes = await this.dataStore.getManifestHashes();
|
|
70
|
+
const remoteManifestFile = await digPeer.propagationServer.getStoreData("manifest.dat");
|
|
71
|
+
const remoteManifestHashes = remoteManifestFile.split("\n").filter(Boolean);
|
|
72
|
+
const onChainRootHashes = rootHistory.map((root) => root.root_hash);
|
|
73
|
+
// Check that remote manifest is one behind on-chain root hashes
|
|
74
|
+
if (remoteManifestHashes.length !== onChainRootHashes.length - 1) {
|
|
75
|
+
throw new Error("Remote manifest should be one behind the on-chain root. Cannot push head.");
|
|
76
|
+
}
|
|
77
|
+
// Compare each remote manifest hash with the corresponding on-chain root hash
|
|
78
|
+
for (let i = 0; i < remoteManifestHashes.length; i++) {
|
|
79
|
+
if (remoteManifestHashes[i] !== onChainRootHashes[i]) {
|
|
80
|
+
throw new Error(`Remote manifest does not match on-chain root at index ${i}. Cannot push head.`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
// Get the files for the latest local manifest hash
|
|
84
|
+
const filesToUpload = await this.dataStore.getFileSetForRootHash(localManifestHashes[localManifestHashes.length - 1]);
|
|
85
|
+
if (!filesToUpload.length) {
|
|
86
|
+
console.log("No files to upload.");
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
// Upload files to the remote peer with a progress bar
|
|
90
|
+
await this.runProgressBar(filesToUpload.length, "Store Data", async (progress) => {
|
|
91
|
+
for (const filePath of filesToUpload) {
|
|
92
|
+
const relativePath = path
|
|
93
|
+
.relative(this.storeDir, filePath)
|
|
94
|
+
.replace(/\\/g, "/");
|
|
95
|
+
await digPeer.propagationServer.pushFile(filePath, relativePath);
|
|
96
|
+
progress.increment();
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
}
|
|
66
100
|
// Uploads the store to a specific peer
|
|
67
101
|
async uploadStore(digPeer) {
|
|
68
102
|
const { generationIndex } = await this.uploadPreflight(digPeer);
|
|
69
103
|
const filesToUpload = await (0, deltaUtils_1.getDeltaFiles)(this.dataStore.StoreId, generationIndex, path.resolve(config_1.DIG_FOLDER_PATH, "stores"));
|
|
70
|
-
console.log(filesToUpload);
|
|
71
104
|
if (!filesToUpload.length) {
|
|
72
105
|
console.log("No files to upload.");
|
|
73
106
|
return;
|
|
74
107
|
}
|
|
75
108
|
await this.runProgressBar(filesToUpload.length, "Store Data", async (progress) => {
|
|
76
109
|
for (const filePath of filesToUpload) {
|
|
77
|
-
console.log(`Uploading ${filePath}...`);
|
|
78
110
|
const relativePath = path
|
|
79
111
|
.relative(this.storeDir, filePath)
|
|
80
112
|
.replace(/\\/g, "/");
|
|
@@ -90,12 +122,46 @@ class DigNetwork {
|
|
|
90
122
|
const digNetwork = new DigNetwork(storeId);
|
|
91
123
|
await digNetwork.downloadFiles(true);
|
|
92
124
|
}
|
|
125
|
+
static async findPeerWithStoreKey(storeId, rootHash, key) {
|
|
126
|
+
const peerBlackList = [];
|
|
127
|
+
const serverCoin = new blockchain_1.ServerCoin(storeId);
|
|
128
|
+
while (true) {
|
|
129
|
+
try {
|
|
130
|
+
const digPeers = await serverCoin.sampleCurrentEpoch(1, peerBlackList);
|
|
131
|
+
if (digPeers.length === 0)
|
|
132
|
+
break;
|
|
133
|
+
const peerIp = digPeers[0];
|
|
134
|
+
const digPeer = new DigPeer_1.DigPeer(peerIp, storeId);
|
|
135
|
+
const storeResponse = await digPeer.contentServer.headStore({
|
|
136
|
+
hasRootHash: rootHash,
|
|
137
|
+
});
|
|
138
|
+
if (storeResponse.success &&
|
|
139
|
+
storeResponse.headers?.["x-has-rootHash"] === "true") {
|
|
140
|
+
if (!key)
|
|
141
|
+
return peerIp;
|
|
142
|
+
const keyResponse = await digPeer.contentServer.headKey(key);
|
|
143
|
+
if (keyResponse.success &&
|
|
144
|
+
keyResponse.headers?.["x-key-exists"] === "true") {
|
|
145
|
+
return peerIp;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
peerBlackList.push(peerIp);
|
|
149
|
+
}
|
|
150
|
+
catch (error) {
|
|
151
|
+
console.error("Error while sampling the epoch or contacting peer:", error);
|
|
152
|
+
break;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
93
157
|
static unsubscribeFromStore(storeId) {
|
|
94
|
-
fs.rmdirSync(path.join(config_1.DIG_FOLDER_PATH, "stores", storeId), {
|
|
158
|
+
fs.rmdirSync(path.join(config_1.DIG_FOLDER_PATH, "stores", storeId), {
|
|
159
|
+
recursive: true,
|
|
160
|
+
});
|
|
95
161
|
fs.unlinkSync(path.join(config_1.DIG_FOLDER_PATH, "stores", storeId + ".json"));
|
|
96
162
|
}
|
|
97
163
|
// Downloads files from the network based on the manifest
|
|
98
|
-
async downloadFiles(forceDownload = false, renderProgressBar = true) {
|
|
164
|
+
async downloadFiles(forceDownload = false, renderProgressBar = true, skipData = false) {
|
|
99
165
|
try {
|
|
100
166
|
const rootHistory = await this.dataStore.getRootHistory();
|
|
101
167
|
if (!rootHistory.length)
|
|
@@ -124,10 +190,12 @@ class DigNetwork {
|
|
|
124
190
|
const datFileContent = JSON.parse(fs.readFileSync(datFilePath, "utf-8"));
|
|
125
191
|
if (datFileContent.root !== rootHash)
|
|
126
192
|
throw new Error("Root hash mismatch");
|
|
127
|
-
|
|
128
|
-
const
|
|
129
|
-
|
|
130
|
-
|
|
193
|
+
if (!skipData) {
|
|
194
|
+
for (const file of Object.keys(datFileContent.files)) {
|
|
195
|
+
const filePath = (0, hashUtils_1.getFilePathFromSha256)(datFileContent.files[file].sha256, path.join(this.storeDir, "data"));
|
|
196
|
+
const isInDataDir = filePath.startsWith(path.join(this.storeDir, "data"));
|
|
197
|
+
await this.downloadFileFromPeers((0, hashUtils_1.getFilePathFromSha256)(datFileContent.files[file].sha256, "data"), filePath, forceDownload || !isInDataDir);
|
|
198
|
+
}
|
|
131
199
|
}
|
|
132
200
|
if (localManifestHashes[i] !== rootHash)
|
|
133
201
|
newRootHashes.push(rootHash);
|
|
@@ -216,7 +284,9 @@ class DigNetwork {
|
|
|
216
284
|
noTTYOutput: true,
|
|
217
285
|
}, cli_progress_1.Presets.shades_classic);
|
|
218
286
|
const progress = multiBar.create(total, 0, { name });
|
|
219
|
-
await task(progress).finally(() =>
|
|
287
|
+
await task(progress).finally(() => {
|
|
288
|
+
multiBar.stop();
|
|
289
|
+
});
|
|
220
290
|
}
|
|
221
291
|
}
|
|
222
292
|
exports.DigNetwork = DigNetwork;
|
|
@@ -50,5 +50,7 @@ export declare class DataStore {
|
|
|
50
50
|
isSynced(): Promise<boolean>;
|
|
51
51
|
hasMetaWritePermissions(publicSyntheticKey?: Buffer): Promise<boolean>;
|
|
52
52
|
updateMetadata(metadata: DataStoreMetadata): Promise<DataStoreDriver>;
|
|
53
|
+
getFileSetForRootHash(rootHash: string): Promise<string[]>;
|
|
54
|
+
getManifestHashes(): string[];
|
|
53
55
|
}
|
|
54
56
|
//# sourceMappingURL=DataStore.d.ts.map
|
|
@@ -1 +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;
|
|
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;AAQjD,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;IA+Cd,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAiChE,iBAAiB,IAAI,MAAM,EAAE;CAUrC"}
|
|
@@ -13,6 +13,7 @@ const Wallet_1 = require("./Wallet");
|
|
|
13
13
|
const config_1 = require("../utils/config");
|
|
14
14
|
const coins_1 = require("./coins");
|
|
15
15
|
const utils_1 = require("../utils");
|
|
16
|
+
const hashUtils_1 = require("../utils/hashUtils");
|
|
16
17
|
const DataIntegrityTree_1 = require("../DataIntegrityTree");
|
|
17
18
|
const prompts_1 = require("../prompts");
|
|
18
19
|
const FileCache_1 = require("../utils/FileCache");
|
|
@@ -406,5 +407,27 @@ class DataStore {
|
|
|
406
407
|
}
|
|
407
408
|
return updateStoreResponse.newStore;
|
|
408
409
|
}
|
|
410
|
+
async getFileSetForRootHash(rootHash) {
|
|
411
|
+
const datFilePath = path_1.default.join(config_1.STORE_PATH, this.storeId, `${rootHash}.dat`);
|
|
412
|
+
const datFileContent = JSON.parse(fs_1.default.readFileSync(datFilePath, "utf-8"));
|
|
413
|
+
const heightDatFilePath = path_1.default.join(config_1.STORE_PATH, this.storeId, "height.json");
|
|
414
|
+
const manifestFilePath = path_1.default.join(config_1.STORE_PATH, this.storeId, "manifest.dat");
|
|
415
|
+
const filesInvolved = [];
|
|
416
|
+
filesInvolved.push(manifestFilePath);
|
|
417
|
+
filesInvolved.push(datFilePath);
|
|
418
|
+
filesInvolved.push(heightDatFilePath);
|
|
419
|
+
for (const [fileKey, fileData] of Object.entries(datFileContent.files)) {
|
|
420
|
+
const filepath = path_1.default.join(config_1.STORE_PATH, this.storeId, "data", fileKey);
|
|
421
|
+
const filePath = (0, hashUtils_1.getFilePathFromSha256)(datFileContent.files[fileKey].sha256, path_1.default.join(config_1.STORE_PATH, this.storeId, "data"));
|
|
422
|
+
filesInvolved.push(filePath);
|
|
423
|
+
}
|
|
424
|
+
return filesInvolved;
|
|
425
|
+
}
|
|
426
|
+
getManifestHashes() {
|
|
427
|
+
const manifestFilePath = path_1.default.join(config_1.STORE_PATH, this.storeId, "manifest.dat");
|
|
428
|
+
return fs_1.default.existsSync(manifestFilePath)
|
|
429
|
+
? fs_1.default.readFileSync(manifestFilePath, "utf-8").split("\n").filter(Boolean)
|
|
430
|
+
: [];
|
|
431
|
+
}
|
|
409
432
|
}
|
|
410
433
|
exports.DataStore = DataStore;
|
|
@@ -7,6 +7,13 @@ export declare class FullNodePeer {
|
|
|
7
7
|
static connect(): Promise<Peer>;
|
|
8
8
|
private static isPortReachable;
|
|
9
9
|
private static isValidIpAddress;
|
|
10
|
+
/**
|
|
11
|
+
* Retrieves the TRUSTED_FULLNODE IP from the environment
|
|
12
|
+
* and verifies if it is a valid IP address.
|
|
13
|
+
*
|
|
14
|
+
* @returns {string | null} The valid IP address or null if invalid
|
|
15
|
+
*/
|
|
16
|
+
private static getTrustedFullNode;
|
|
10
17
|
private static fetchNewPeerIPs;
|
|
11
18
|
private static getPeerIPs;
|
|
12
19
|
private static createPeerProxy;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FullNodePeer.d.ts","sourceRoot":"","sources":["../../src/blockchain/FullNodePeer.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAmBxC,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAC,UAAU,CAAkD;IAC3E,OAAO,CAAC,MAAM,CAAC,uBAAuB,CAA0B;IAChE,OAAO,CAAC,IAAI,CAAO;IAQnB,OAAO;WAIa,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAK5C,OAAO,CAAC,MAAM,CAAC,eAAe;IAiB9B,OAAO,CAAC,MAAM,CAAC,gBAAgB;
|
|
1
|
+
{"version":3,"file":"FullNodePeer.d.ts","sourceRoot":"","sources":["../../src/blockchain/FullNodePeer.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAmBxC,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAC,UAAU,CAAkD;IAC3E,OAAO,CAAC,MAAM,CAAC,uBAAuB,CAA0B;IAChE,OAAO,CAAC,IAAI,CAAO;IAQnB,OAAO;WAIa,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAK5C,OAAO,CAAC,MAAM,CAAC,eAAe;IAiB9B,OAAO,CAAC,MAAM,CAAC,gBAAgB;IAM/B;;;;;OAKG;IACH,OAAO,CAAC,MAAM,CAAC,kBAAkB;mBASZ,eAAe;mBAiDf,UAAU;IAyB/B,OAAO,CAAC,MAAM,CAAC,eAAe;mBAgDT,WAAW;IAgGzB,OAAO,IAAI,IAAI;WAIF,mBAAmB,CACrC,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,OAAO,CAAC;CAwBpB"}
|
|
@@ -48,12 +48,24 @@ class FullNodePeer {
|
|
|
48
48
|
const ipv4Regex = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/;
|
|
49
49
|
return ipv4Regex.test(ip);
|
|
50
50
|
}
|
|
51
|
-
|
|
51
|
+
/**
|
|
52
|
+
* Retrieves the TRUSTED_FULLNODE IP from the environment
|
|
53
|
+
* and verifies if it is a valid IP address.
|
|
54
|
+
*
|
|
55
|
+
* @returns {string | null} The valid IP address or null if invalid
|
|
56
|
+
*/
|
|
57
|
+
static getTrustedFullNode() {
|
|
52
58
|
const trustedNodeIp = process.env.TRUSTED_FULLNODE || null;
|
|
59
|
+
if (trustedNodeIp && FullNodePeer.isValidIpAddress(trustedNodeIp)) {
|
|
60
|
+
return trustedNodeIp;
|
|
61
|
+
}
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
static async fetchNewPeerIPs() {
|
|
65
|
+
const trustedNodeIp = FullNodePeer.getTrustedFullNode();
|
|
53
66
|
const priorityIps = [];
|
|
54
67
|
// Prioritize trustedNodeIp
|
|
55
68
|
if (trustedNodeIp &&
|
|
56
|
-
FullNodePeer.isValidIpAddress(trustedNodeIp) &&
|
|
57
69
|
(await FullNodePeer.isPortReachable(trustedNodeIp, FULLNODE_PORT))) {
|
|
58
70
|
priorityIps.push(trustedNodeIp);
|
|
59
71
|
}
|
|
@@ -107,18 +119,38 @@ class FullNodePeer {
|
|
|
107
119
|
}
|
|
108
120
|
return FullNodePeer.memoizedFetchNewPeerIPs();
|
|
109
121
|
}
|
|
110
|
-
static createPeerProxy(peer
|
|
122
|
+
static createPeerProxy(peer) {
|
|
111
123
|
return new Proxy(peer, {
|
|
112
124
|
get: (target, prop) => {
|
|
113
125
|
const originalMethod = target[prop];
|
|
114
126
|
if (typeof originalMethod === "function") {
|
|
115
127
|
return async (...args) => {
|
|
128
|
+
let timeoutId;
|
|
129
|
+
// Start the timeout to forget the peer after 1 minute
|
|
130
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
131
|
+
timeoutId = setTimeout(() => {
|
|
132
|
+
FullNodePeer.cachedPeer = null;
|
|
133
|
+
reject(new Error("Operation timed out. Reconnecting to a new peer."));
|
|
134
|
+
}, 60000); // 1 minute
|
|
135
|
+
});
|
|
116
136
|
try {
|
|
117
|
-
|
|
137
|
+
// Run the original method and race it against the timeout
|
|
138
|
+
const result = await Promise.race([
|
|
139
|
+
originalMethod.apply(target, args),
|
|
140
|
+
timeoutPromise,
|
|
141
|
+
]);
|
|
142
|
+
// Clear the timeout if the operation succeeded
|
|
143
|
+
if (timeoutId) {
|
|
144
|
+
clearTimeout(timeoutId);
|
|
145
|
+
}
|
|
146
|
+
return result;
|
|
118
147
|
}
|
|
119
148
|
catch (error) {
|
|
120
|
-
|
|
149
|
+
// If the error is WebSocket-related or timeout, reset the peer
|
|
150
|
+
if (error.message.includes("WebSocket") || error.message.includes("Operation timed out")) {
|
|
121
151
|
FullNodePeer.cachedPeer = null;
|
|
152
|
+
// @ts-ignore
|
|
153
|
+
FullNodePeer.memoizedFetchNewPeerIPs.cache.clear();
|
|
122
154
|
const newPeer = await FullNodePeer.getBestPeer();
|
|
123
155
|
return newPeer[prop](...args);
|
|
124
156
|
}
|
|
@@ -149,7 +181,7 @@ class FullNodePeer {
|
|
|
149
181
|
if (ip) {
|
|
150
182
|
try {
|
|
151
183
|
const peer = await datalayer_driver_1.Peer.new(`${ip}:${FULLNODE_PORT}`, false, certFile, keyFile);
|
|
152
|
-
return FullNodePeer.createPeerProxy(peer
|
|
184
|
+
return FullNodePeer.createPeerProxy(peer);
|
|
153
185
|
}
|
|
154
186
|
catch (error) {
|
|
155
187
|
console.error(`Failed to create peer for IP ${ip}: ${error.message}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAKrC,eAAO,MAAM,oBAAoB,qEACmC,CAAC;AAErE,eAAO,MAAM,UAAU,UAAU,CAAC;AAClC,eAAO,MAAM,sBAAsB,qEACiC,CAAC;AAErE,eAAO,MAAM,eAAe,QACqC,CAAC;AAElE,eAAO,MAAM,UAAU,QAAuC,CAAC;AAE/D,eAAO,MAAM,aAAa,QAAkC,CAAC;AAC7D,eAAO,MAAM,gBAAgB,QAAgD,CAAC;AAE9E,eAAO,MAAM,mBAAmB,YAAa,MAAM,KAAG,MACN,CAAC;AAEjD,eAAO,MAAM,iBAAiB,YAAa,MAAM,KAAG,MACL,CAAC;AAEhD,eAAO,MAAM,mBAAmB,QAAO,IAItC,CAAC;AAEF,eAAO,MAAM,SAAS,WAAY,MAAM,KAAG,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAKrC,eAAO,MAAM,oBAAoB,qEACmC,CAAC;AAErE,eAAO,MAAM,UAAU,UAAU,CAAC;AAClC,eAAO,MAAM,sBAAsB,qEACiC,CAAC;AAErE,eAAO,MAAM,eAAe,QACqC,CAAC;AAElE,eAAO,MAAM,UAAU,QAAuC,CAAC;AAE/D,eAAO,MAAM,aAAa,QAAkC,CAAC;AAC7D,eAAO,MAAM,gBAAgB,QAAgD,CAAC;AAE9E,eAAO,MAAM,mBAAmB,YAAa,MAAM,KAAG,MACN,CAAC;AAEjD,eAAO,MAAM,iBAAiB,YAAa,MAAM,KAAG,MACL,CAAC;AAEhD,eAAO,MAAM,mBAAmB,QAAO,IAItC,CAAC;AAEF,eAAO,MAAM,SAAS,WAAY,MAAM,KAAG,IAQ1C,CAAC;AAEF,eAAO,MAAM,cAAc,YAAa,MAAM,KAAG,IAQhD,CAAC;AAqBF,eAAO,MAAM,YAAY,YACd,MAAM,KACd;IACD,QAAQ,EAAE;QACR,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,EAAE,MAAM,CAAC;KACrB,CAAC;CAYH,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,aAAa,QAAO,MAAM,EAOtC,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,QAAa,OAAO,CAAC,MAAM,GAAG,IAAI,CAkC9D,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,aAAa,YAAa,MAAM,KAAG,SAS/C,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,YAAa,MAAM,KAAG,SAoBjD,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,YACjB,MAAM,OACV,MAAM,SACJ,GAAG,KACT,IAMF,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,YAAa,MAAM,OAAO,MAAM,KAAG,IAcjE,CAAC"}
|
package/dist/utils/config.js
CHANGED
|
@@ -49,9 +49,7 @@ const createInitialConfig = () => {
|
|
|
49
49
|
};
|
|
50
50
|
exports.createInitialConfig = createInitialConfig;
|
|
51
51
|
const setRemote = (remote) => {
|
|
52
|
-
|
|
53
|
-
throw new Error("Config file not found.");
|
|
54
|
-
}
|
|
52
|
+
(0, exports.ensureDigConfig)("");
|
|
55
53
|
const config = JSON.parse(fs.readFileSync(exports.CONFIG_FILE_PATH, "utf-8"));
|
|
56
54
|
config.remote = remote;
|
|
57
55
|
fs.writeFileSync(exports.CONFIG_FILE_PATH, JSON.stringify(config, null, 4));
|
|
@@ -59,9 +57,7 @@ const setRemote = (remote) => {
|
|
|
59
57
|
};
|
|
60
58
|
exports.setRemote = setRemote;
|
|
61
59
|
const setActiveStore = (storeId) => {
|
|
62
|
-
|
|
63
|
-
throw new Error("Config file not found.");
|
|
64
|
-
}
|
|
60
|
+
(0, exports.ensureDigConfig)("");
|
|
65
61
|
const config = JSON.parse(fs.readFileSync(exports.CONFIG_FILE_PATH, "utf-8"));
|
|
66
62
|
config.active_store = storeId;
|
|
67
63
|
fs.writeFileSync(exports.CONFIG_FILE_PATH, JSON.stringify(config, null, 4));
|
|
@@ -151,9 +147,7 @@ exports.getActiveStoreId = getActiveStoreId;
|
|
|
151
147
|
* @throws Will throw an error if the config file does not exist or cannot be parsed.
|
|
152
148
|
*/
|
|
153
149
|
const loadDigConfig = (baseDir) => {
|
|
154
|
-
|
|
155
|
-
throw new Error(`Configuration file not found at ${exports.CONFIG_FILE_PATH}`);
|
|
156
|
-
}
|
|
150
|
+
(0, exports.ensureDigConfig)("");
|
|
157
151
|
try {
|
|
158
152
|
const configContent = fs.readFileSync(exports.CONFIG_FILE_PATH, "utf-8");
|
|
159
153
|
const config = JSON.parse(configContent);
|
|
@@ -173,6 +167,7 @@ exports.loadDigConfig = loadDigConfig;
|
|
|
173
167
|
*/
|
|
174
168
|
const ensureDigConfig = (baseDir) => {
|
|
175
169
|
if (!fs.existsSync(exports.CONFIG_FILE_PATH)) {
|
|
170
|
+
fs.mkdirSync(exports.DIG_FOLDER_PATH, { recursive: true });
|
|
176
171
|
const defaultConfig = { deploy_dir: "./dist" };
|
|
177
172
|
fs.writeFileSync(exports.CONFIG_FILE_PATH, JSON.stringify(defaultConfig, null, 4), "utf-8");
|
|
178
173
|
console.log(`Created new dig.config.json at ${exports.CONFIG_FILE_PATH}`);
|
|
@@ -1,10 +1,4 @@
|
|
|
1
1
|
import { DataIntegrityTree } from "../DataIntegrityTree";
|
|
2
|
-
/**
|
|
3
|
-
* Recursively add all files in a directory to the Merkle tree, skipping the .dig, .git folders, and files in .gitignore.
|
|
4
|
-
* @param datalayer - The DataStoreManager instance.
|
|
5
|
-
* @param dirPath - The directory path.
|
|
6
|
-
* @param baseDir - The base directory for relative paths.
|
|
7
|
-
*/
|
|
8
2
|
export declare const addDirectory: (datalayer: DataIntegrityTree, dirPath: string, baseDir?: string) => Promise<void>;
|
|
9
3
|
/**
|
|
10
4
|
* Calculate the total size of the DIG_FOLDER_PATH
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"directoryUtils.d.ts","sourceRoot":"","sources":["../../src/utils/directoryUtils.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"directoryUtils.d.ts","sourceRoot":"","sources":["../../src/utils/directoryUtils.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AA+BzD,eAAO,MAAM,YAAY,cACZ,iBAAiB,WACnB,MAAM,YACN,MAAM,KACd,OAAO,CAAC,IAAI,CA4Cd,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,eAAgB,MAAM,KAAG,MAiBxD,CAAC"}
|
|
@@ -27,15 +27,29 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
27
27
|
};
|
|
28
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
29
|
exports.calculateFolderSize = exports.addDirectory = void 0;
|
|
30
|
-
const fs = __importStar(require("fs"));
|
|
31
30
|
const path = __importStar(require("path"));
|
|
31
|
+
const fs = __importStar(require("fs"));
|
|
32
32
|
const ignore_1 = __importDefault(require("ignore"));
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
33
|
+
// Custom concurrency handler
|
|
34
|
+
const limitConcurrency = async (concurrencyLimit, tasks) => {
|
|
35
|
+
const executing = [];
|
|
36
|
+
for (const task of tasks) {
|
|
37
|
+
const p = task();
|
|
38
|
+
// Add the new task to the executing array
|
|
39
|
+
executing.push(p);
|
|
40
|
+
// When a task completes, remove it from the executing array
|
|
41
|
+
const cleanup = p.finally(() => {
|
|
42
|
+
executing.splice(executing.indexOf(cleanup), 1);
|
|
43
|
+
});
|
|
44
|
+
// Once the limit is reached, wait for one to complete
|
|
45
|
+
if (executing.length >= concurrencyLimit) {
|
|
46
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
47
|
+
await Promise.race(executing);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// Wait for all remaining tasks to complete
|
|
51
|
+
return Promise.all(executing);
|
|
52
|
+
};
|
|
39
53
|
const addDirectory = async (datalayer, dirPath, baseDir = dirPath) => {
|
|
40
54
|
const ig = (0, ignore_1.default)();
|
|
41
55
|
const gitignorePath = path.join(baseDir, ".gitignore");
|
|
@@ -45,6 +59,7 @@ const addDirectory = async (datalayer, dirPath, baseDir = dirPath) => {
|
|
|
45
59
|
ig.add(gitignoreContent);
|
|
46
60
|
}
|
|
47
61
|
const files = fs.readdirSync(dirPath);
|
|
62
|
+
const tasks = [];
|
|
48
63
|
for (const file of files) {
|
|
49
64
|
const filePath = path.join(dirPath, file);
|
|
50
65
|
const relativePath = path.relative(baseDir, filePath).replace(/\\/g, "/");
|
|
@@ -54,18 +69,22 @@ const addDirectory = async (datalayer, dirPath, baseDir = dirPath) => {
|
|
|
54
69
|
}
|
|
55
70
|
const stat = fs.statSync(filePath);
|
|
56
71
|
if (stat.isDirectory()) {
|
|
57
|
-
|
|
72
|
+
// Recursively process the directory
|
|
73
|
+
tasks.push(() => (0, exports.addDirectory)(datalayer, filePath, baseDir));
|
|
58
74
|
}
|
|
59
75
|
else {
|
|
60
|
-
|
|
76
|
+
// Add a task for each file to be processed
|
|
77
|
+
tasks.push(() => new Promise((resolve, reject) => {
|
|
61
78
|
const stream = fs.createReadStream(filePath);
|
|
62
79
|
datalayer
|
|
63
80
|
.upsertKey(stream, Buffer.from(relativePath).toString("hex"))
|
|
64
|
-
.then(resolve)
|
|
81
|
+
.then(() => resolve())
|
|
65
82
|
.catch(reject);
|
|
66
|
-
});
|
|
83
|
+
}));
|
|
67
84
|
}
|
|
68
85
|
}
|
|
86
|
+
// Run tasks with limited concurrency (set the concurrency limit as needed)
|
|
87
|
+
await limitConcurrency(10, tasks); // Adjust 10 based on your system limits
|
|
69
88
|
};
|
|
70
89
|
exports.addDirectory = addDirectory;
|
|
71
90
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dignetwork/dig-sdk",
|
|
3
|
-
"version": "0.0.1-alpha.
|
|
3
|
+
"version": "0.0.1-alpha.21",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
"merkletreejs": "^0.4.0",
|
|
42
42
|
"nanospinner": "^1.1.0",
|
|
43
43
|
"nconf": "^0.12.1",
|
|
44
|
+
"p-limit": "^6.1.0",
|
|
44
45
|
"superagent": "^10.0.0"
|
|
45
46
|
},
|
|
46
47
|
"devDependencies": {
|