diff --git a/tools/erc-repository-indexer/erc-contract-indexer/package-lock.json b/tools/erc-repository-indexer/erc-contract-indexer/package-lock.json index c65c78b95..d99d7e2ff 100644 --- a/tools/erc-repository-indexer/erc-contract-indexer/package-lock.json +++ b/tools/erc-repository-indexer/erc-contract-indexer/package-lock.json @@ -9,9 +9,11 @@ "version": "0.1.0", "license": "Apache-2.0", "dependencies": { + "@types/lodash": "^4.17.14", "ahocorasick": "^1.0.2", "dotenv": "^16.4.5", - "ethers": "^6.13.4" + "ethers": "^6.13.4", + "lodash": "^4.17.21" }, "devDependencies": { "@hashgraph/sdk": "^2.55.0", @@ -1775,6 +1777,12 @@ "pretty-format": "^29.0.0" } }, + "node_modules/@types/lodash": { + "version": "4.17.14", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.14.tgz", + "integrity": "sha512-jsxagdikDiDBeIRaPYtArcT8my4tN1og7MtMRquFT3XNA6axxyHDRUemqDz/taRDdOUn0GnGHRCuff4q48sW9A==", + "license": "MIT" + }, "node_modules/@types/node": { "version": "22.10.1", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.1.tgz", @@ -4105,6 +4113,12 @@ "node": ">=8" } }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, "node_modules/lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", diff --git a/tools/erc-repository-indexer/erc-contract-indexer/package.json b/tools/erc-repository-indexer/erc-contract-indexer/package.json index d4ad144d0..f5e5b4690 100644 --- a/tools/erc-repository-indexer/erc-contract-indexer/package.json +++ b/tools/erc-repository-indexer/erc-contract-indexer/package.json @@ -22,8 +22,10 @@ "typescript": "^5.7.2" }, "dependencies": { + "@types/lodash": "^4.17.14", "ahocorasick": "^1.0.2", "dotenv": "^16.4.5", - "ethers": "^6.13.4" + "ethers": "^6.13.4", + "lodash": "^4.17.21" } } diff --git a/tools/erc-repository-indexer/erc-contract-indexer/src/services/registryGenerator.ts b/tools/erc-repository-indexer/erc-contract-indexer/src/services/registryGenerator.ts index 3a6c66880..2768c5d45 100644 --- a/tools/erc-repository-indexer/erc-contract-indexer/src/services/registryGenerator.ts +++ b/tools/erc-repository-indexer/erc-contract-indexer/src/services/registryGenerator.ts @@ -23,6 +23,7 @@ import path from 'path'; import constants from '../utils/constants'; import { ERCOutputInterface } from '../schemas/ERCRegistrySchemas'; import { Helper } from '../utils/helper'; +import _ from 'lodash'; export class RegistryGenerator { /** @@ -108,33 +109,47 @@ export class RegistryGenerator { } /** - * Updates a registry file with new contracts, removing duplicates if any. - * @param {string} filePath - Path to the registry file - * @param {ERCOutputInterface[]} newContracts - New contracts to add to registry - * @returns {Promise} Promise that resolves when registry is updated + * Updates a registry file with new contracts by merging them with existing contracts, + * ensuring the registry remains sorted and free of duplicates. + * + * @param {string} filePath - The file path to the registry file. + * @param {ERCOutputInterface[]} newContracts - The new contracts to add to the registry. + * @returns {Promise} - A promise that resolves once the registry is successfully updated. + * * @private */ private async updateRegistry( filePath: string, newContracts: ERCOutputInterface[] ): Promise { + let uniqueContracts: ERCOutputInterface[] = []; const fileContent = this.readContentsFromFile(filePath); const existingContracts = fileContent ? (JSON.parse(fileContent) as ERCOutputInterface[]) : []; - // Create a Map to deduplicate contracts by contractId - const contractMap = new Map( - [...existingContracts, ...newContracts].map((contract) => [ - contract.contractId, - contract, - ]) - ); + if (!existingContracts.length) { + uniqueContracts = newContracts; + } else if ( + // Since both arrays are sorted in ascending order, if the `contractId` of the last item in `existingContracts` + // is less than the `contractId` of the first item in `newContracts`, just merged the contracts and remove dups without sorting. + existingContracts[existingContracts.length - 1].contractId < + newContracts[0].contractId + ) { + uniqueContracts = _.chain([...existingContracts, ...newContracts]) // merge contracts + .uniqBy('contractId') // Remove duplicates based on contractId + .value(); // Extract the final array + } else { + uniqueContracts = _.chain([...existingContracts, ...newContracts]) // merge contracts + .uniqBy('contractId') // Remove duplicates based on contractId + .sortBy((contract) => Number(contract.contractId.split('.')[2])) // Sort by the numeric value of contractId + .value(); // Extract the final array + } + + await this.writeContentsToFile(filePath, uniqueContracts); // Convert Map values back to array for file writing - const uniqueContracts = Array.from(contractMap.values()); - await this.writeContentsToFile(filePath, uniqueContracts); console.log( `Finished writing ${newContracts.length} new ERC token contracts to registry.` ); diff --git a/tools/erc-repository-indexer/erc-contract-indexer/src/utils/helper.ts b/tools/erc-repository-indexer/erc-contract-indexer/src/utils/helper.ts index ec70325a2..c9f02d2d0 100644 --- a/tools/erc-repository-indexer/erc-contract-indexer/src/utils/helper.ts +++ b/tools/erc-repository-indexer/erc-contract-indexer/src/utils/helper.ts @@ -19,8 +19,8 @@ */ import axios, { AxiosInstance } from 'axios'; -import path from 'path'; import constants from './constants'; +import path from 'path'; export class Helper { /**