@dignetwork/dig-sdk 0.0.1-alpha.2 → 0.0.1-alpha.20

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.
@@ -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":"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"}
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, { ...options, disableInitialize: true });
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 ? manifestContent[manifestContent.length - 1] : null;
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
- // Create a read stream and pipe it through a decompression stream using the same algorithm (gzip)
440
- const readStream = fs.createReadStream(filePath);
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(): Promise<{
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":"AAAA,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,CAAC,IAAI,CAAM;gBAEtB,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;IAMjC,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,IAAI,OAAO,CAAC;QAChC,OAAO,EAAE,OAAO,CAAC;QACjB,OAAO,CAAC,EAAE,IAAI,CAAC,mBAAmB,CAAC;KACpC,CAAC;IAMK,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC;YA0ClC,IAAI;YAuEJ,SAAS;YAMT,gBAAgB;YAiChB,KAAK;CAuDpB"}
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 = `http://${this.ipAddress}/chia.${this.storeId}.${rootHash}/${key}`;
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 = `http://${this.ipAddress}/.well-known`;
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 = `http://${this.ipAddress}/.well-known/stores`;
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 = `http://${this.ipAddress}/`;
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 = `http://${this.ipAddress}/${this.storeId}`;
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 = `http://${this.ipAddress}/${this.storeId}/${key}`;
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
- const url = `http://${this.ipAddress}/${this.storeId}`;
64
- console.log({ url });
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 = `http://${this.ipAddress}/${this.storeId}/${key}`;
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 = 80;
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;IA+ChB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;WAgCrC,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;WAQtD,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAM5C,aAAa,CACxB,aAAa,GAAE,OAAe,EAC9B,iBAAiB,GAAE,OAAc,GAChC,OAAO,CAAC,IAAI,CAAC;YAmFF,mBAAmB;YAWnB,kBAAkB;YASlB,oBAAoB;YASpB,qBAAqB;YAuErB,cAAc;CAkB7B"}
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,EAAE,MAAM,GACV,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), { recursive: true });
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
- for (const file of Object.keys(datFileContent.files)) {
128
- const filePath = (0, hashUtils_1.getFilePathFromSha256)(datFileContent.files[file].sha256, path.join(this.storeDir, "data"));
129
- const isInDataDir = filePath.startsWith(path.join(this.storeDir, "data"));
130
- await this.downloadFileFromPeers((0, hashUtils_1.getFilePathFromSha256)(datFileContent.files[file].sha256, "data"), filePath, forceDownload || !isInDataDir);
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(() => multiBar.stop());
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;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"}
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;mBAOV,eAAe;mBAkDf,UAAU;IAyB/B,OAAO,CAAC,MAAM,CAAC,eAAe;mBA4BT,WAAW;IAgGzB,OAAO,IAAI,IAAI;WAIF,mBAAmB,CACrC,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,OAAO,CAAC;CAwBpB"}
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
- static async fetchNewPeerIPs() {
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, certFile, keyFile) {
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
- return await originalMethod.apply(target, args);
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
- if (error.message.includes("WebSocket")) {
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, certFile, keyFile);
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,IAU1C,CAAC;AAEF,eAAO,MAAM,cAAc,YAAa,MAAM,KAAG,IAUhD,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,SAY/C,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,YAAa,MAAM,KAAG,SAmBjD,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"}
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"}
@@ -49,9 +49,7 @@ const createInitialConfig = () => {
49
49
  };
50
50
  exports.createInitialConfig = createInitialConfig;
51
51
  const setRemote = (remote) => {
52
- if (!fs.existsSync(exports.CONFIG_FILE_PATH)) {
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
- if (!fs.existsSync(exports.CONFIG_FILE_PATH)) {
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
- if (!fs.existsSync(exports.CONFIG_FILE_PATH)) {
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;AAEzD;;;;;GAKG;AACH,eAAO,MAAM,YAAY,cACZ,iBAAiB,WACnB,MAAM,YACN,MAAM,KACd,OAAO,CAAC,IAAI,CAmCd,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,eAAgB,MAAM,KAAG,MAiBxD,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
- * Recursively add all files in a directory to the Merkle tree, skipping the .dig, .git folders, and files in .gitignore.
35
- * @param datalayer - The DataStoreManager instance.
36
- * @param dirPath - The directory path.
37
- * @param baseDir - The base directory for relative paths.
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
- await (0, exports.addDirectory)(datalayer, filePath, baseDir);
72
+ // Recursively process the directory
73
+ tasks.push(() => (0, exports.addDirectory)(datalayer, filePath, baseDir));
58
74
  }
59
75
  else {
60
- await new Promise((resolve, reject) => {
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.2",
3
+ "version": "0.0.1-alpha.20",
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": {