From 2ed00067039e054e4bfb7d693c098ff7afe34c66 Mon Sep 17 00:00:00 2001 From: Aurora Poppyseed <30662672+poppyseedDev@users.noreply.github.com> Date: Tue, 10 Dec 2024 19:06:32 -0300 Subject: [PATCH 1/6] mini change --- contracts/contracts/sample4.sol | 4 +--- contracts/test/sample/sample3.ts | 4 ++-- contracts/test/sample/sample4.ts | 20 -------------------- 3 files changed, 3 insertions(+), 25 deletions(-) diff --git a/contracts/contracts/sample4.sol b/contracts/contracts/sample4.sol index 1679f4a..bcd08f8 100644 --- a/contracts/contracts/sample4.sol +++ b/contracts/contracts/sample4.sol @@ -15,9 +15,7 @@ contract EncryptedCounter4 is SepoliaZamaFHEVMConfig { function incrementBy(einput amount, bytes calldata inputProof) public { // Initialize counter if it doesn't exist - if (!TFHE.isInitialized(counters[msg.sender])) { - counters[msg.sender] = TFHE.asEuint8(0); - } + counters[msg.sender] = TFHE.asEuint8(0); // Convert input to euint8 and add to sender's counter euint8 incrementAmount = TFHE.asEuint8(amount, inputProof); diff --git a/contracts/test/sample/sample3.ts b/contracts/test/sample/sample3.ts index 5eb1a16..5793341 100644 --- a/contracts/test/sample/sample3.ts +++ b/contracts/test/sample/sample3.ts @@ -20,7 +20,7 @@ describe("EncryptedCounter3", function () { this.instances = await createInstance(); // Set up instances for testing }); - it("should increment counter multiple times and decrypt the result", async function () { + it("should increment counter and decrypt the result", async function () { // Create encrypted input for amount to increment by const input = this.instances.createEncryptedInput(this.contractAddress, this.signers.alice.address); input.add8(5); // Increment by 5 as an example @@ -30,7 +30,7 @@ describe("EncryptedCounter3", function () { const tx = await this.counterContract.incrementBy(encryptedAmount.handles[0], encryptedAmount.inputProof); await tx.wait(); - const tx4 = await this.counterContract.connect(this.signers.carol).requestDecryptCounter({ gasLimit: 5_000_000 }); + const tx4 = await this.counterContract.connect(this.signers.carol).requestDecryptCounter(); await tx4.wait(); // Wait for decryption to complete diff --git a/contracts/test/sample/sample4.ts b/contracts/test/sample/sample4.ts index 6652d45..fb252cb 100644 --- a/contracts/test/sample/sample4.ts +++ b/contracts/test/sample/sample4.ts @@ -19,26 +19,6 @@ describe("EncryptedCounter4", function () { this.instances = await createInstance(); }); - it("should initialize the counter to zero", async function () { - const counterValue = await this.counterContract.getCounter(); - expect(counterValue); // Expect initial value to be zero - }); - - it("should increment by arbitrary encrypted amount", async function () { - // Create encrypted input for amount to increment by - const input = this.instances.createEncryptedInput(this.contractAddress, this.signers.alice.address); - input.add8(5); // Increment by 5 as an example - const encryptedAmount = await input.encrypt(); - - // Call incrementBy with encrypted amount - const tx = await this.counterContract.incrementBy(encryptedAmount.handles[0], encryptedAmount.inputProof); - await tx.wait(); - - // Get updated counter value - const counterValue = await this.counterContract.getCounter(); - expect(counterValue); // Counter should be incremented by 5 - }); - it("should allow reencryption and decryption of counter value", async function () { const input = this.instances.createEncryptedInput(this.contractAddress, this.signers.alice.address); input.add8(1); // Increment by 1 as an example From ded1346282e44f2472f480a4fda75beddb50d1bf Mon Sep 17 00:00:00 2001 From: Aurora Poppyseed <30662672+poppyseedDev@users.noreply.github.com> Date: Wed, 11 Dec 2024 13:54:34 -0300 Subject: [PATCH 2/6] internal added --- contracts/contracts/sample1.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/contracts/sample1.sol b/contracts/contracts/sample1.sol index c5ba2dd..4fe7d76 100644 --- a/contracts/contracts/sample1.sol +++ b/contracts/contracts/sample1.sol @@ -11,8 +11,8 @@ import "fhevm/config/ZamaFHEVMConfig.sol"; /// @custom:notice This contract has limited real-world utility and serves primarily as a starting point /// for understanding how to implement basic FHE operations in Solidity contract EncryptedCounter1 is SepoliaZamaFHEVMConfig { - euint8 counter; - euint8 CONST_ONE; + euint8 internal counter; + euint8 internal CONST_ONE; constructor() { // Initialize counter with an encrypted zero value From e9933334fd68624557ac9815b4eb1598b0107da4 Mon Sep 17 00:00:00 2001 From: Aurora Poppyseed <30662672+poppyseedDev@users.noreply.github.com> Date: Fri, 13 Dec 2024 17:43:50 -0300 Subject: [PATCH 3/6] adding did to dapp --- .../{ => confidentialCounter}/sample1.sol | 2 +- .../{ => confidentialCounter}/sample2.sol | 0 .../{ => confidentialCounter}/sample3.sol | 0 .../{ => confidentialCounter}/sample4.sol | 0 contracts/contracts/decIdentity/Diploma.sol | 214 +++++++++++ .../contracts/decIdentity/EmployerClaim.sol | 207 +++++++++++ contracts/contracts/decIdentity/IdMapping.sol | 114 ++++++ .../contracts/decIdentity/PassportID.sol | 243 ++++++++++++ .../sample1.ts | 0 .../sample2.ts | 0 .../sample3.ts | 0 .../sample4.ts | 0 contracts/test/decIdentity/diploma.ts | 351 ++++++++++++++++++ .../decIdentity/fixture/Diploma.fixture.ts | 12 + .../fixture/EmployerClaim.fixture.ts | 21 ++ .../decIdentity/fixture/IdMapping.fixture.ts | 13 + .../decIdentity/fixture/PassportID.fixture.ts | 12 + contracts/test/decIdentity/idMapping.ts | 106 ++++++ contracts/test/decIdentity/passportID.ts | 164 ++++++++ 19 files changed, 1458 insertions(+), 1 deletion(-) rename contracts/contracts/{ => confidentialCounter}/sample1.sol (96%) rename contracts/contracts/{ => confidentialCounter}/sample2.sol (100%) rename contracts/contracts/{ => confidentialCounter}/sample3.sol (100%) rename contracts/contracts/{ => confidentialCounter}/sample4.sol (100%) create mode 100644 contracts/contracts/decIdentity/Diploma.sol create mode 100644 contracts/contracts/decIdentity/EmployerClaim.sol create mode 100644 contracts/contracts/decIdentity/IdMapping.sol create mode 100644 contracts/contracts/decIdentity/PassportID.sol rename contracts/test/{sample => confidentialCounter}/sample1.ts (100%) rename contracts/test/{sample => confidentialCounter}/sample2.ts (100%) rename contracts/test/{sample => confidentialCounter}/sample3.ts (100%) rename contracts/test/{sample => confidentialCounter}/sample4.ts (100%) create mode 100644 contracts/test/decIdentity/diploma.ts create mode 100644 contracts/test/decIdentity/fixture/Diploma.fixture.ts create mode 100644 contracts/test/decIdentity/fixture/EmployerClaim.fixture.ts create mode 100644 contracts/test/decIdentity/fixture/IdMapping.fixture.ts create mode 100644 contracts/test/decIdentity/fixture/PassportID.fixture.ts create mode 100644 contracts/test/decIdentity/idMapping.ts create mode 100644 contracts/test/decIdentity/passportID.ts diff --git a/contracts/contracts/sample1.sol b/contracts/contracts/confidentialCounter/sample1.sol similarity index 96% rename from contracts/contracts/sample1.sol rename to contracts/contracts/confidentialCounter/sample1.sol index 4fe7d76..2730e78 100644 --- a/contracts/contracts/sample1.sol +++ b/contracts/contracts/confidentialCounter/sample1.sol @@ -12,7 +12,7 @@ import "fhevm/config/ZamaFHEVMConfig.sol"; /// for understanding how to implement basic FHE operations in Solidity contract EncryptedCounter1 is SepoliaZamaFHEVMConfig { euint8 internal counter; - euint8 internal CONST_ONE; + euint8 internal immutable CONST_ONE; constructor() { // Initialize counter with an encrypted zero value diff --git a/contracts/contracts/sample2.sol b/contracts/contracts/confidentialCounter/sample2.sol similarity index 100% rename from contracts/contracts/sample2.sol rename to contracts/contracts/confidentialCounter/sample2.sol diff --git a/contracts/contracts/sample3.sol b/contracts/contracts/confidentialCounter/sample3.sol similarity index 100% rename from contracts/contracts/sample3.sol rename to contracts/contracts/confidentialCounter/sample3.sol diff --git a/contracts/contracts/sample4.sol b/contracts/contracts/confidentialCounter/sample4.sol similarity index 100% rename from contracts/contracts/sample4.sol rename to contracts/contracts/confidentialCounter/sample4.sol diff --git a/contracts/contracts/decIdentity/Diploma.sol b/contracts/contracts/decIdentity/Diploma.sol new file mode 100644 index 0000000..a7fc29d --- /dev/null +++ b/contracts/contracts/decIdentity/Diploma.sol @@ -0,0 +1,214 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import "fhevm/lib/TFHE.sol"; +import "./IdMapping.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "fhevm/config/ZamaFHEVMConfig.sol"; + +/** + * @title Diploma + * @author ZAMA + * @dev Contract for managing encrypted diploma records using TFHE encryption + * @notice Allows universities to register encrypted diploma data and graduates to generate claims + */ +contract Diploma is SepoliaZamaFHEVMConfig, AccessControl { + /// @dev Constants + bytes32 public constant REGISTRAR_ROLE = keccak256("REGISTRAR_ROLE"); + bytes32 public constant OWNER_ROLE = keccak256("OWNER_ROLE"); + + /// @dev Custom errors + /// @notice Thrown when attempting to register a diploma for a user who already has one + error DiplomaAlreadyRegistered(); + /// @notice Thrown when attempting to access diploma data for a user who doesn't have one registered + error DiplomaNotRegistered(); + /// @notice Thrown when sender doesn't have permission to access the encrypted data + error AccessNotPermitted(); + /// @notice Thrown when claim generation fails, includes failure data + /// @param data The error data returned from the failed claim generation + error ClaimGenerationFailed(bytes data); + + /// @dev Structure to hold encrypted diploma data + struct DiplomaData { + euint64 id; // Encrypted unique diploma ID + ebytes64 university; // Encrypted university identifier + euint16 degree; // Encrypted degree identifier + ebytes64 grade; // Encrypted grade + } + + /// @dev Instance of IdMapping contract + IdMapping private idMapping; + + /// @dev Mapping to store diploma records by user ID + mapping(uint256 => DiplomaData) private diplomaRecords; + /// @dev Mapping to track registered diplomas + mapping(uint256 => bool) public registered; + /// @dev Mapping for degree identifiers to degree names + mapping(uint16 => string) public degreeTypes; + + /// @dev Event emitted when a diploma is registered + event DiplomaRegistered(address indexed graduate); + /// @dev Event emitted when a claim is generated + event ClaimGenerated(address indexed graduate, address claimAddress, string claimFn); + + /** + * @dev Constructor to initialize the contract with IdMapping address + * @param _idMappingAddress Address of the IdMapping contract + */ + constructor(address _idMappingAddress) { + idMapping = IdMapping(_idMappingAddress); + _grantRole(OWNER_ROLE, msg.sender); // Admin role for contract owner + _grantRole(REGISTRAR_ROLE, msg.sender); // Registrar role for contract owner + + // Initialize degree mappings + degreeTypes[1] = "Electrical Engineering (B.Eng)"; + degreeTypes[2] = "Mechanical Engineering (B.Eng)"; + degreeTypes[3] = "Computer Science (B.Sc)"; + degreeTypes[4] = "Civil Engineering (B.Eng)"; + degreeTypes[5] = "Chemical Engineering (B.Eng)"; + // Graduate degrees start from 1001 + degreeTypes[1001] = "Electrical Engineering (M.Eng)"; + degreeTypes[1002] = "Mechanical Engineering (M.Eng)"; + degreeTypes[1003] = "Computer Science (M.Sc)"; + // Doctoral degrees start from 2001 + degreeTypes[2001] = "Electrical Engineering (Ph.D)"; + degreeTypes[2002] = "Computer Science (Ph.D)"; + } + + /** + * @dev Adds a new registrar address + * @param registrar Address to be granted registrar role + */ + function addRegistrar(address registrar) external onlyRole(OWNER_ROLE) { + _grantRole(REGISTRAR_ROLE, registrar); + } + + /** + * @dev Removes a registrar address + * @param registrar Address to be revoked registrar role + */ + function removeRegistrar(address registrar) external onlyRole(OWNER_ROLE) { + _revokeRole(REGISTRAR_ROLE, registrar); + } + + /** + * @dev Retrieves the degree type for a given degree ID + * @param degreeId The ID of the degree type to retrieve + * @return The name/description of the degree type + */ + function getDegreeType(uint16 degreeId) public view returns (string memory) { + return degreeTypes[degreeId]; + } + + /** + * @dev Registers a new encrypted diploma for a user + * @param userId ID of the user to register diploma for + * @param university Encrypted university identifier + * @param degree Encrypted degree type + * @param grade Encrypted grade + * @param inputProof Proof for encrypted inputs + * @return bool indicating success + */ + function registerDiploma( + uint256 userId, + einput university, + einput degree, + einput grade, + bytes calldata inputProof + ) public virtual onlyRole(REGISTRAR_ROLE) returns (bool) { + if (registered[userId]) revert DiplomaAlreadyRegistered(); + + // Generate a new encrypted diploma ID + euint64 newId = TFHE.randEuint64(); + + // Store the encrypted diploma data + diplomaRecords[userId] = DiplomaData({ + id: newId, + university: TFHE.asEbytes64(university, inputProof), + degree: TFHE.asEuint16(degree, inputProof), + grade: TFHE.asEbytes64(grade, inputProof) + }); + + registered[userId] = true; // Mark the diploma as registered + + // Get the address associated with the user ID + address addressToBeAllowed = idMapping.getAddr(userId); + + // Allow the graduate to access their own data + TFHE.allow(diplomaRecords[userId].id, addressToBeAllowed); + TFHE.allow(diplomaRecords[userId].university, addressToBeAllowed); + TFHE.allow(diplomaRecords[userId].degree, addressToBeAllowed); + TFHE.allow(diplomaRecords[userId].grade, addressToBeAllowed); + + // Allow the contract to access the data + TFHE.allowThis(diplomaRecords[userId].id); + TFHE.allowThis(diplomaRecords[userId].university); + TFHE.allowThis(diplomaRecords[userId].degree); + TFHE.allowThis(diplomaRecords[userId].grade); + + emit DiplomaRegistered(addressToBeAllowed); // Emit event for diploma registration + + return true; + } + + /** + * @dev Retrieves encrypted university identifier for a user + * @param userId ID of the user to get university for + * @return euint8 Encrypted university identifier + */ + function getMyUniversity(uint256 userId) public view virtual returns (ebytes64) { + if (!registered[userId]) revert DiplomaNotRegistered(); + return diplomaRecords[userId].university; + } + + /** + * @dev Retrieves encrypted degree type for a user + * @param userId ID of the user to get degree for + * @return euint8 Encrypted degree type + */ + function getMyDegree(uint256 userId) public view virtual returns (euint16) { + if (!registered[userId]) revert DiplomaNotRegistered(); + return diplomaRecords[userId].degree; + } + + /** + * @dev Retrieves encrypted grade for a user + * @param userId ID of the user to get grade for + * @return euint8 Encrypted grade + */ + function getMyGrade(uint256 userId) public view virtual returns (ebytes64) { + if (!registered[userId]) revert DiplomaNotRegistered(); + return diplomaRecords[userId].grade; + } + + /** + * @dev Checks if a diploma is registered for a user + * @param userId ID of the user to check + * @return bool indicating if diploma exists + */ + function hasDiploma(uint256 userId) public view virtual returns (bool) { + return registered[userId]; + } + + /** + * @dev Generates a claim for a diploma + * @param claimAddress Address of the claim contract + * @param claimFn Function signature to call on claim contract + */ + function generateClaim(address claimAddress, string memory claimFn) public { + /// @dev Only the msg.sender that is registered under the user ID can make the claim + uint256 userId = idMapping.getId(msg.sender); + + /// @dev Grant temporary access for graduate's data to be used in claim generation + TFHE.allowTransient(diplomaRecords[userId].degree, claimAddress); + + /// @dev Ensure the sender can access this graduate's data + if (!TFHE.isSenderAllowed(diplomaRecords[userId].degree)) revert AccessNotPermitted(); + + /// @dev Attempt the external call and capture the result + (bool success, bytes memory data) = claimAddress.call(abi.encodeWithSignature(claimFn, userId)); + if (!success) revert ClaimGenerationFailed(data); + + emit ClaimGenerated(msg.sender, claimAddress, claimFn); /// @dev Emit event for claim generation + } +} diff --git a/contracts/contracts/decIdentity/EmployerClaim.sol b/contracts/contracts/decIdentity/EmployerClaim.sol new file mode 100644 index 0000000..56d41fd --- /dev/null +++ b/contracts/contracts/decIdentity/EmployerClaim.sol @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import "fhevm/lib/TFHE.sol"; +import "./PassportID.sol"; +import "./Diploma.sol"; +import "@openzeppelin/contracts/access/Ownable2Step.sol"; +import "fhevm/config/ZamaFHEVMConfig.sol"; + +/** + * @title EmployerClaim + * @author ZAMA + * @dev Contract for managing encrypted claims about users' age and education credentials + * @notice Allows generation and verification of encrypted claims for employment verification + */ +contract EmployerClaim is SepoliaZamaFHEVMConfig, Ownable2Step { + /// @dev Age threshold timestamp for adult verification (Jan 1, 2006 - 18 years on Jan 1, 2024) + uint64 private constant AGE_THRESHOLD_TIMESTAMP = 1136070000; + /// @dev Required degree level for education verification (Computer Science (B.Sc)) + uint16 private constant REQUIRED_DEGREE_LEVEL = 3; + /// @dev Constant representing an invalid claim ID + uint256 private constant INVALID_CLAIM = 0; + euint64 private _AGE_THRESHOLD; + euint16 private _REQUIRED_DEGREE; + + /// @dev Error thrown when an invalid claim ID is provided + error InvalidClaimId(); + /// @dev Error thrown when an invalid contract address is provided + error InvalidContractAddress(); + /// @dev Error thrown when caller is not authorized + error NotAuthorized(); + + /// @dev Counter for tracking the latest claim ID + uint64 public lastClaimId = 0; + /// @dev Mapping of claim IDs to encrypted boolean results for adult claims + mapping(uint64 => ebool) private adultClaims; + /// @dev Mapping of claim IDs to encrypted boolean results for degree claims + mapping(uint64 => ebool) private degreeClaims; + /// @dev Mapping of user IDs to encrypted boolean results for verified claims + mapping(uint256 => ebool) private verifiedClaims; + + /// @dev Emitted when an adult claim is generated + /// @param claimId The ID of the generated claim + /// @param userId The ID of the user the claim is for + event AdultClaimGenerated(uint64 claimId, uint256 userId); + /// @dev Emitted when a degree claim is generated + /// @param claimId The ID of the generated claim + /// @param userId The ID of the user the claim is for + event DegreeClaimGenerated(uint64 claimId, uint256 userId); + + /// @dev Instance of IdMapping contract for user ID management + IdMapping private idMapping; + /// @dev Instance of PassportID contract for identity verification + PassportID private passportContract; + /// @dev Instance of Diploma contract for education verification + Diploma private diplomaContract; + + /** + * @dev Constructor to initialize the contract with required contract addresses + * @param _idMappingAddress Address of the IdMapping contract + * @param _passportAddress Address of the PassportID contract + * @param _diplomaAddress Address of the Diploma contract + * @custom:throws InvalidContractAddress if any address is zero + */ + constructor(address _idMappingAddress, address _passportAddress, address _diplomaAddress) Ownable(msg.sender) { + if (_idMappingAddress == address(0) || _passportAddress == address(0) || _diplomaAddress == address(0)) + revert InvalidContractAddress(); + + idMapping = IdMapping(_idMappingAddress); + passportContract = PassportID(_passportAddress); + diplomaContract = Diploma(_diplomaAddress); + + /// Set age threshold to 18 years (in Unix timestamp) + _AGE_THRESHOLD = TFHE.asEuint64(AGE_THRESHOLD_TIMESTAMP); + + /// Use constant for required degree + _REQUIRED_DEGREE = TFHE.asEuint16(REQUIRED_DEGREE_LEVEL); + + TFHE.allowThis(_AGE_THRESHOLD); + TFHE.allowThis(_REQUIRED_DEGREE); + } + + /** + * @dev Generates an encrypted claim verifying if a user is above 18 years old + * @param userId The ID of the user to generate the claim for + * @return The ID of the generated claim + * @custom:throws NotAuthorized if caller is not the passport contract + * @custom:emits AdultClaimGenerated when claim is generated + */ + function generateAdultClaim(uint256 userId) public returns (uint64) { + if (msg.sender != address(passportContract)) revert NotAuthorized(); + + /// Retrieve the address associated with the user ID + address addressToBeAllowed = idMapping.getAddr(userId); + + /// Retrieve the user's encrypted birthdate from the PassportID contract + euint64 birthdate = passportContract.getBirthdate(userId); + + lastClaimId++; + + /// Check if birthdate indicates user is over 18 + ebool isAdult = TFHE.le(birthdate, _AGE_THRESHOLD); + + /// Store the result of the claim + adultClaims[lastClaimId] = isAdult; + + /// Grant access to the claim to both the contract and user for verification purposes + TFHE.allowThis(isAdult); + TFHE.allow(isAdult, addressToBeAllowed); + + /// Emit an event for the generated claim + emit AdultClaimGenerated(lastClaimId, userId); + + return lastClaimId; + } + + /** + * @dev Retrieves the result of an adult claim + * @param claimId The ID of the claim to retrieve + * @return The encrypted boolean result of the claim + * @custom:throws InvalidClaimId if claim ID is invalid + */ + function getAdultClaim(uint64 claimId) public view returns (ebool) { + if (claimId == 0 || claimId > lastClaimId) revert InvalidClaimId(); + return adultClaims[claimId]; + } + + /** + * @dev Generates an encrypted claim verifying if a user has required degree credentials + * @param userId The ID of the user to generate the claim for + * @return The ID of the generated claim + * @custom:throws NotAuthorized if caller is not the diploma contract + * @custom:emits DegreeClaimGenerated when claim is generated + */ + function generateDegreeClaim(uint256 userId) public returns (uint64) { + if (msg.sender != address(diplomaContract)) revert NotAuthorized(); + + /// Retrieve the address associated with the user ID + address addressToBeAllowed = idMapping.getAddr(userId); + + /// Get the diploma data from the Diploma contract + euint16 userUniversity = diplomaContract.getMyDegree(userId); + + lastClaimId++; + + /// Check if university and degree match requirements + ebool degreeMatch = TFHE.eq(userUniversity, _REQUIRED_DEGREE); + + /// Store the result of the claim + degreeClaims[lastClaimId] = degreeMatch; + + /// Grant access to the claim + TFHE.allowThis(degreeMatch); + TFHE.allow(degreeMatch, addressToBeAllowed); + + /// Emit an event for the generated claim + emit DegreeClaimGenerated(lastClaimId, userId); + + return lastClaimId; + } + + /** + * @dev Retrieves the result of a degree claim + * @param claimId The ID of the claim to retrieve + * @return The encrypted boolean result of the claim + * @custom:throws InvalidClaimId if claim ID is invalid + */ + function getDegreeClaim(uint64 claimId) public view returns (ebool) { + if (claimId == 0 || claimId > lastClaimId) revert InvalidClaimId(); + return degreeClaims[claimId]; + } + + /** + * @dev Verifies both adult and degree claims for a user + * @param userId The ID of the user to verify claims for + * @param adultClaim The ID of the adult claim to verify + * @param degreeClaim The ID of the degree claim to verify + * @custom:throws InvalidClaimId if either claim ID is invalid + * @notice This function combines adult and degree claims into a single verification + */ + function verifyClaims(uint256 userId, uint64 adultClaim, uint64 degreeClaim) public { + if (adultClaim == INVALID_CLAIM || adultClaim > lastClaimId) revert InvalidClaimId(); + if (degreeClaim == INVALID_CLAIM || degreeClaim > lastClaimId) revert InvalidClaimId(); + + ebool isAdult = adultClaims[adultClaim]; + ebool degreeMatch = degreeClaims[degreeClaim]; + + ebool verify = TFHE.and(isAdult, degreeMatch); + + /// Store the verification result under the userId mapping + verifiedClaims[userId] = verify; + + /// Grant access to the claim + TFHE.allowThis(verify); + TFHE.allow(verify, owner()); + } + + /** + * @dev Retrieves the result of a verified claim for a user + * @param userId The ID of the user to get the verified claim for + * @return The encrypted boolean result of the verified claim + * @notice Returns the combined verification status of adult and degree claims + */ + function getVerifyClaim(uint256 userId) public view returns (ebool) { + return verifiedClaims[userId]; + } +} diff --git a/contracts/contracts/decIdentity/IdMapping.sol b/contracts/contracts/decIdentity/IdMapping.sol new file mode 100644 index 0000000..4d28ea4 --- /dev/null +++ b/contracts/contracts/decIdentity/IdMapping.sol @@ -0,0 +1,114 @@ +/// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/access/Ownable2Step.sol"; +import "fhevm/config/ZamaFHEVMConfig.sol"; + +/** + * @title IdMapping + * @author ZAMA + * @notice Manages unique ID mappings between addresses and sequential IDs + * @dev Inherits from Ownable2Step for secure ownership transfer + */ +contract IdMapping is SepoliaZamaFHEVMConfig, Ownable2Step { + /// Custom errors + /// @notice Thrown when attempting to generate an ID for an address that already has one + error IdAlreadyGenerated(); + /// @notice Thrown when attempting to use the zero address + error InvalidAddress(); + /// @notice Thrown when the maximum ID value has been reached + error IdOverflow(); + /// @notice Thrown when trying to look up an ID for an address that hasn't generated one + error NoIdGenerated(); + /// @notice Thrown when attempting to use an ID that doesn't exist + error InvalidId(); + /// @notice Thrown when no address is found for a given ID + error NoAddressFound(); + + /// @notice Maps user addresses to their unique IDs + mapping(address => uint256) public addressToId; + /// @dev Maps unique IDs back to user addresses + mapping(uint256 => address) private idToAddress; + /// @dev Counter for assigning sequential IDs, starts at 1 + uint256 private nextId = 1; + + /** + * @notice Emitted when a new ID is generated for a user + * @param user The address of the user receiving the ID + * @param id The unique ID assigned to the user + */ + event IdGenerated(address indexed user, uint256 indexed id); + + /** + * @notice Initializes the contract with the deployer as owner + * @dev Sets initial ID counter to 1 + */ + constructor() Ownable(msg.sender) { + nextId = 1; + } + + /** + * @notice Generates a unique ID for the calling address + * @dev Each address can only generate one ID. IDs are assigned sequentially starting from 1 + * @return uint256 The newly generated ID + * @custom:throws IdAlreadyGenerated if caller already has an ID + * @custom:throws InvalidAddress if caller is zero address + * @custom:throws IdOverflow if maximum ID value is reached + */ + function generateId() public returns (uint256) { + if (addressToId[msg.sender] != 0) revert IdAlreadyGenerated(); + if (msg.sender == address(0)) revert InvalidAddress(); + + uint256 newId = nextId; + + addressToId[msg.sender] = newId; + idToAddress[newId] = msg.sender; + nextId++; + + emit IdGenerated(msg.sender, newId); + return newId; + } + + /** + * @notice Looks up the ID associated with a given address + * @dev Reverts if address has no ID or is zero address + * @param _addr The address to lookup + * @return uint256 The ID associated with the address + * @custom:throws InvalidAddress if provided address is zero address + * @custom:throws NoIdGenerated if address has no ID assigned + */ + function getId(address _addr) public view returns (uint256) { + if (_addr == address(0)) revert InvalidAddress(); + if (addressToId[_addr] == 0) revert NoIdGenerated(); + return addressToId[_addr]; + } + + /** + * @notice Looks up the address associated with a given ID + * @dev Reverts if ID is invalid or has no associated address + * @param _id The ID to lookup + * @return address The address associated with the ID + * @custom:throws InvalidId if ID is 0 or greater than the last assigned ID + * @custom:throws NoAddressFound if no address is associated with the ID + */ + function getAddr(uint256 _id) public view returns (address) { + if (_id <= 0 || _id >= nextId) revert InvalidId(); + address addr = idToAddress[_id]; + if (addr == address(0)) revert NoAddressFound(); + return addr; + } + + /** + * @notice Removes an address's ID mapping + * @dev Only callable by contract owner. Removes both address->ID and ID->address mappings + * @param _addr The address whose ID mapping should be reset + * @custom:throws NoIdGenerated if address has no ID assigned + */ + function resetIdForAddress(address _addr) external onlyOwner { + uint256 id = addressToId[_addr]; + if (id == 0) revert NoIdGenerated(); + + delete addressToId[_addr]; + delete idToAddress[id]; + } +} diff --git a/contracts/contracts/decIdentity/PassportID.sol b/contracts/contracts/decIdentity/PassportID.sol new file mode 100644 index 0000000..a717e85 --- /dev/null +++ b/contracts/contracts/decIdentity/PassportID.sol @@ -0,0 +1,243 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import "fhevm/lib/TFHE.sol"; +import "./IdMapping.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "fhevm/config/ZamaFHEVMConfig.sol"; + +/** + * @title PassportID + * @author ZAMA + * @notice Manages encrypted passport identity data and verification claims + * @dev Implements role-based access control for registrars and admins to manage identity registration + */ +contract PassportID is SepoliaZamaFHEVMConfig, AccessControl { + /// @dev Constants + bytes32 public constant REGISTRAR_ROLE = keccak256("REGISTRAR_ROLE"); + bytes32 public constant OWNER_ROLE = keccak256("OWNER_ROLE"); + + /// @dev Custom errors + /// @notice Thrown when attempting to register an identity for a user who already has one + error AlreadyRegistered(); + /// @notice Thrown when attempting to access identity data for a user who doesn't have one registered + error IdentityNotRegistered(); + /// @notice Thrown when sender doesn't have permission to access the encrypted data + error AccessNotPermitted(); + /// @notice Thrown when claim generation fails, includes failure data + /// @param data The error data returned from the failed claim generation + error ClaimGenerationFailed(bytes data); + error InvalidField(); + + /** + * @dev Structure to hold encrypted identity data + * @param id Encrypted unique identifier for the identity record + * @param biodata Encrypted biometric data like fingerprints or facial data + * @param firstname Encrypted legal first name from passport + * @param lastname Encrypted legal last name from passport + * @param birthdate Encrypted date of birth in unix timestamp format + */ + struct Identity { + euint64 id; /// @dev Encrypted unique ID + ebytes64 biodata; /// @dev Encrypted biodata (e.g., biometric data or hashed identity data) + ebytes64 firstname; /// @dev Encrypted first name + ebytes64 lastname; /// @dev Encrypted last name + euint64 birthdate; /// @dev Encrypted birthdate for age verification + } + + /// @dev Instance of IdMapping contract + IdMapping private idMapping; + + /// @dev Mapping to store identities by user ID + mapping(uint256 => Identity) private citizenIdentities; + /// @dev Mapping to track registered identities + mapping(uint256 => bool) public registered; + + /// @dev Event emitted when an identity is registered + event IdentityRegistered(address indexed user); + + /** + * @notice Initializes the passport identity management system + * @dev Sets up FHEVM config and grants admin/registrar roles to deployer + * @param _idMappingAddress Address of the IdMapping contract for user ID management + */ + constructor(address _idMappingAddress) { + idMapping = IdMapping(_idMappingAddress); + _grantRole(OWNER_ROLE, msg.sender); /// @dev Admin role for contract owner + _grantRole(REGISTRAR_ROLE, msg.sender); /// @dev Registrar role for contract owner + } + + /** + * @notice Grants registrar privileges to a new address + * @dev Only callable by admin role + * @param registrar Address to be granted registrar permissions + */ + function addRegistrar(address registrar) external onlyRole(OWNER_ROLE) { + _grantRole(REGISTRAR_ROLE, registrar); + } + + /** + * @notice Revokes registrar privileges from an address + * @dev Only callable by admin role + * @param registrar Address to have registrar permissions revoked + */ + function removeRegistrar(address registrar) external onlyRole(OWNER_ROLE) { + _revokeRole(REGISTRAR_ROLE, registrar); + } + + /** + * @notice Creates a new encrypted identity record + * @dev Only admin role can register new identities. All data is stored in encrypted form + * @param userId Unique identifier for the user from IdMapping contract + * @param biodata Encrypted biometric/identity data with proof + * @param firstname Encrypted first name with proof + * @param lastname Encrypted last name with proof + * @param birthdate Encrypted birthdate with proof + * @param inputProof Zero-knowledge proof validating the encrypted inputs + * @return bool True if registration was successful + * @custom:throws AlreadyRegistered if userId already has an identity registered + */ + function registerIdentity( + uint256 userId, + einput biodata, + einput firstname, + einput lastname, + einput birthdate, + bytes calldata inputProof + ) public virtual onlyRole(REGISTRAR_ROLE) returns (bool) { + if (registered[userId]) revert AlreadyRegistered(); + + /// @dev Generate a new encrypted unique ID + euint64 newId = TFHE.randEuint64(); + + /// @dev Store the encrypted identity data + citizenIdentities[userId] = Identity({ + id: newId, + biodata: TFHE.asEbytes64(biodata, inputProof), + firstname: TFHE.asEbytes64(firstname, inputProof), + lastname: TFHE.asEbytes64(lastname, inputProof), + birthdate: TFHE.asEuint64(birthdate, inputProof) + }); + + registered[userId] = true; /// @dev Mark the identity as registered + + /// @dev Get the address associated with the user ID + address addressToBeAllowed = idMapping.getAddr(userId); + + /// @dev Allow the user to access their own data + TFHE.allow(citizenIdentities[userId].id, addressToBeAllowed); + TFHE.allow(citizenIdentities[userId].biodata, addressToBeAllowed); + TFHE.allow(citizenIdentities[userId].firstname, addressToBeAllowed); + TFHE.allow(citizenIdentities[userId].lastname, addressToBeAllowed); + TFHE.allow(citizenIdentities[userId].birthdate, addressToBeAllowed); + + /// @dev Allow the contract to access the data + TFHE.allowThis(citizenIdentities[userId].id); + TFHE.allowThis(citizenIdentities[userId].biodata); + TFHE.allowThis(citizenIdentities[userId].firstname); + TFHE.allowThis(citizenIdentities[userId].lastname); + TFHE.allowThis(citizenIdentities[userId].birthdate); + + emit IdentityRegistered(addressToBeAllowed); /// @dev Emit event for identity registration + + return true; + } + + /** + * @notice Retrieves the complete encrypted identity record for a user + * @dev Returns all encrypted identity fields as a tuple + * @param userId ID of the user whose identity to retrieve + * @return Tuple containing (id, biodata, firstname, lastname, birthdate) + * @custom:throws IdentityNotRegistered if no identity exists for userId + */ + function getIdentity(uint256 userId) public view virtual returns (euint64, ebytes64, ebytes64, ebytes64, euint64) { + if (!registered[userId]) revert IdentityNotRegistered(); + return ( + citizenIdentities[userId].id, + citizenIdentities[userId].biodata, + citizenIdentities[userId].firstname, + citizenIdentities[userId].lastname, + citizenIdentities[userId].birthdate + ); + } + + /** + * @notice Retrieves only the encrypted birthdate for a user + * @dev Useful for age verification claims + * @param userId ID of the user whose birthdate to retrieve + * @return Encrypted birthdate as euint64 + * @custom:throws IdentityNotRegistered if no identity exists for userId + */ + function getBirthdate(uint256 userId) public view virtual returns (euint64) { + if (!registered[userId]) revert IdentityNotRegistered(); + return citizenIdentities[userId].birthdate; + } + + /** + * @notice Retrieves only the encrypted first name for a user + * @dev Useful for identity verification claims + * @param userId ID of the user whose first name to retrieve + * @return Encrypted first name as euint8 + * @custom:throws IdentityNotRegistered if no identity exists for userId + */ + function getMyIdentityFirstname(uint256 userId) public view virtual returns (ebytes64) { + if (!registered[userId]) revert IdentityNotRegistered(); + return citizenIdentities[userId].firstname; + } + + /** + * @notice Generates a verification claim using the user's identity data + * @dev Temporarily grants claim contract access to required encrypted data + * @param claimAddress Contract address that will process the claim + * @param claimFn Function signature in the claim contract to call + * @custom:throws AccessNotPermitted if sender lacks permission to access data + * @custom:throws ClaimGenerationFailed if external claim call fails + */ + function generateClaim(address claimAddress, string memory claimFn) public { + /// @dev Only the msg.sender that is registered under the user ID can make the claim + uint256 userId = idMapping.getId(msg.sender); + + /// @dev Grant temporary access for citizen's birthdate to be used in claim generation + TFHE.allowTransient(citizenIdentities[userId].birthdate, claimAddress); + + /// @dev Ensure the sender can access this citizen's birthdate + if (!TFHE.isSenderAllowed(citizenIdentities[userId].birthdate)) revert AccessNotPermitted(); + + /// @dev Attempt the external call and capture the result + (bool success, bytes memory data) = claimAddress.call(abi.encodeWithSignature(claimFn, userId)); + if (!success) revert ClaimGenerationFailed(data); + } + + /** + * @notice Generates a verification claim using the user's identity data + * @dev Temporarily grants claim contract access to required encrypted data + * @param claimAddress Contract address that will process the claim + * @param claimFn Function signature in the claim contract to call + * @custom:throws AccessNotPermitted if sender lacks permission to access data + * @custom:throws ClaimGenerationFailed if external claim call fails + */ + function generateClaim(address claimAddress, string memory claimFn, string[] memory fields) public { + /// @dev Only the msg.sender that is registered under the user ID can make the claim + uint256 userId = idMapping.getId(msg.sender); + + /// @dev Grant temporary access for each requested field + for (uint i = 0; i < fields.length; i++) { + if (bytes(fields[i]).length == 0) revert InvalidField(); + + if (keccak256(bytes(fields[i])) == keccak256(bytes("id"))) { + TFHE.allowTransient(citizenIdentities[userId].id, claimAddress); + /// @dev Ensure the sender can access this citizen's university + if (!TFHE.isSenderAllowed(citizenIdentities[userId].id)) revert AccessNotPermitted(); + } else if (keccak256(bytes(fields[i])) == keccak256(bytes("birthdate"))) { + TFHE.allowTransient(citizenIdentities[userId].birthdate, claimAddress); + if (!TFHE.isSenderAllowed(citizenIdentities[userId].birthdate)) revert AccessNotPermitted(); + } else { + revert InvalidField(); + } + } + + /// @dev Attempt the external call and capture the result + (bool success, bytes memory data) = claimAddress.call(abi.encodeWithSignature(claimFn, userId)); + if (!success) revert ClaimGenerationFailed(data); + } +} diff --git a/contracts/test/sample/sample1.ts b/contracts/test/confidentialCounter/sample1.ts similarity index 100% rename from contracts/test/sample/sample1.ts rename to contracts/test/confidentialCounter/sample1.ts diff --git a/contracts/test/sample/sample2.ts b/contracts/test/confidentialCounter/sample2.ts similarity index 100% rename from contracts/test/sample/sample2.ts rename to contracts/test/confidentialCounter/sample2.ts diff --git a/contracts/test/sample/sample3.ts b/contracts/test/confidentialCounter/sample3.ts similarity index 100% rename from contracts/test/sample/sample3.ts rename to contracts/test/confidentialCounter/sample3.ts diff --git a/contracts/test/sample/sample4.ts b/contracts/test/confidentialCounter/sample4.ts similarity index 100% rename from contracts/test/sample/sample4.ts rename to contracts/test/confidentialCounter/sample4.ts diff --git a/contracts/test/decIdentity/diploma.ts b/contracts/test/decIdentity/diploma.ts new file mode 100644 index 0000000..5a31278 --- /dev/null +++ b/contracts/test/decIdentity/diploma.ts @@ -0,0 +1,351 @@ +import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers"; +import { toBufferBE } from "bigint-buffer"; +import { expect } from "chai"; +import type { FhevmInstance } from "fhevmjs"; + +import type { Diploma, EmployerClaim, IdMapping, PassportID } from "../../types"; +import { createInstance } from "../instance"; +import { reencryptEbool, reencryptEbytes64, reencryptEuint8, reencryptEuint16 } from "../reencrypt"; +import { getSigners, initSigners } from "../signers"; +import { bigIntToBytes64 } from "../utils"; +import { deployEmployerClaimFixture } from "./fixture/EmployerClaim.fixture"; + +/** + * Utility function to convert a bigint value to a 256-bit byte array + * @param value - The bigint value to convert + * @returns A Uint8Array representing the 256-bit byte array + */ +export const bigIntToBytes256 = (value: bigint) => { + return new Uint8Array(toBufferBE(value, 256)); +}; + +/** + * Integration test suite for PassportID and EmployerClaim contracts + * Tests the core functionality of diploma registration, verification and claim generation + */ +describe("Diploma", function () { + let passportID: PassportID; + let employerClaim: EmployerClaim; + let diplomaID: Diploma; + let idMapping: IdMapping; + + /** + * Initialize test signers before running any tests + * Sets up alice and other signers that will be used across test cases + */ + before(async function () { + await initSigners(); + this.signers = await getSigners(); + }); + + /** + * Deploy fresh contract instances before each test + * Sets up clean state with new PassportID, EmployerClaim, Diploma and IdMapping contracts + */ + beforeEach(async function () { + const deployment = await deployEmployerClaimFixture(); + employerClaim = deployment.employerClaim; + passportID = deployment.passportID; + diplomaID = deployment.diploma; + idMapping = deployment.idMapping; + + this.employerClaimAddress = await employerClaim.getAddress(); + this.diplomaAddress = await diplomaID.getAddress(); + this.passportIDAddress = await passportID.getAddress(); + this.idMappingAddress = await idMapping.getAddress(); + + this.instances = await createInstance(); + }); + + /** + * Helper function to register a diploma for a user + */ + async function registerDiploma( + userId: bigint, + instance: FhevmInstance, + diplomaAddress: string, + signer: HardhatEthersSigner, + university = bigIntToBytes64(8n), + degree = 8, + grade = bigIntToBytes64(8n), + ) { + const input = instance.createEncryptedInput(diplomaAddress, signer.address); + const encryptedData = await input.addBytes64(university).add16(degree).addBytes64(grade).encrypt(); + + await diplomaID + .connect(signer) + .registerDiploma( + userId, + encryptedData.handles[0], + encryptedData.handles[1], + encryptedData.handles[2], + encryptedData.inputProof, + ); + } + + // /** + // * Helper function to setup reencryption + // */ + // async function setupReencryption(instance: FhevmInstance, signer: HardhatEthersSigner, contractAddress: string) { + // const { publicKey, privateKey } = instance.generateKeypair(); + // const eip712 = instance.createEIP712(publicKey, contractAddress); + // const signature = await signer.signTypedData(eip712.domain, { Reencrypt: eip712.types.Reencrypt }, eip712.message); + + // return { publicKey, privateKey, signature: signature.replace("0x", "") }; + // } + + /** + * Helper function to register identity + */ + async function registerIdentity( + userId: bigint, + instance: FhevmInstance, + passportAddress: string, + signer: HardhatEthersSigner, + biodata = bigIntToBytes64(8n), + firstname = bigIntToBytes64(8n), + lastname = bigIntToBytes64(8n), + birthdate = 946681200n, // Sat Jan 01 2000 - 24 years old + ) { + const input = instance.createEncryptedInput(passportAddress, signer.address); + const encryptedData = await input + .addBytes64(biodata) + .addBytes64(firstname) + .addBytes64(lastname) + .add64(birthdate) + .encrypt(); + + await passportID + .connect(signer) + .registerIdentity( + userId, + encryptedData.handles[0], + encryptedData.handles[1], + encryptedData.handles[2], + encryptedData.handles[3], + encryptedData.inputProof, + ); + } + + it("should register an identity successfully", async function () { + await idMapping.connect(this.signers.alice).generateId(); + const userId = await idMapping.getId(this.signers.alice); + + await registerDiploma(userId, this.instances, this.diplomaAddress, this.signers.alice); + + expect(await diplomaID.registered(userId)); + }); + + it("should prevent duplicate registration for the same user", async function () { + await idMapping.connect(this.signers.alice).generateId(); + const userId = await idMapping.getId(this.signers.alice); + + await registerDiploma(userId, this.instances, this.diplomaAddress, this.signers.alice); + + await expect( + registerDiploma(userId, this.instances, this.diplomaAddress, this.signers.alice), + ).to.be.revertedWithCustomError(diplomaID, "DiplomaAlreadyRegistered"); + }); + + it("should retrieve the registered identity", async function () { + await idMapping.connect(this.signers.alice).generateId(); + const userId = await idMapping.getId(this.signers.alice); + + await registerDiploma(userId, this.instances, this.diplomaAddress, this.signers.alice); + + const universityHandleAlice = await diplomaID.getMyUniversity(userId); + + const reencryptedUniversity = await reencryptEbytes64( + this.signers, + this.instances, + "alice", + universityHandleAlice, + this.diplomaAddress, + ); + + expect(reencryptedUniversity).to.equal(8); + }); + + it("should generate an degree claim", async function () { + await idMapping.connect(this.signers.alice).generateId(); + const userId = await idMapping.getId(this.signers.alice); + + await registerDiploma(userId, this.instances, this.diplomaAddress, this.signers.alice); + + const tx = await diplomaID + .connect(this.signers.alice) + .generateClaim(this.employerClaimAddress, "generateDegreeClaim(uint256)"); + + await expect(tx).to.emit(employerClaim, "DegreeClaimGenerated"); + + const latestClaimUserId = await employerClaim.lastClaimId(); + const degreeClaim = await employerClaim.getDegreeClaim(latestClaimUserId); + + const reencryptedDegreeClaim = await reencryptEbool( + this.signers, + this.instances, + "alice", + degreeClaim, + this.diplomaAddress, + ); + + expect(reencryptedDegreeClaim).to.equal(0); + }); + + it("should generate both degree and adult claims", async function () { + await idMapping.connect(this.signers.alice).generateId(); + const userId = await idMapping.getId(this.signers.alice); + + await registerDiploma( + userId, + this.instances, + this.diplomaAddress, + this.signers.alice, + bigIntToBytes64(8n), + 3, // Computer Science (B.Sc) + bigIntToBytes64(8n), + ); + + const degreeTx = await diplomaID + .connect(this.signers.alice) + .generateClaim(this.employerClaimAddress, "generateDegreeClaim(uint256)"); + + await expect(degreeTx).to.emit(employerClaim, "DegreeClaimGenerated"); + + const latestDegreeClaimUserId = await employerClaim.lastClaimId(); + const degreeClaim = await employerClaim.getDegreeClaim(latestDegreeClaimUserId); + + await registerIdentity(userId, this.instances, this.passportIDAddress, this.signers.alice); + + const adultTx = await passportID + .connect(this.signers.alice) + .generateClaim(this.employerClaimAddress, "generateAdultClaim(uint256)"); + + await expect(adultTx).to.emit(employerClaim, "AdultClaimGenerated"); + + const latestAdultClaimUserId = await employerClaim.lastClaimId(); + const adultClaim = await employerClaim.getAdultClaim(latestAdultClaimUserId); + + const reencryptedDegreeClaim = await reencryptEbool( + this.signers, + this.instances, + "alice", + degreeClaim, + this.diplomaAddress, + ); + + const reencryptedAdultClaim = await reencryptEbool( + this.signers, + this.instances, + "alice", + adultClaim, + this.diplomaAddress, + ); + + expect(reencryptedDegreeClaim).to.equal(1); + expect(reencryptedAdultClaim).to.equal(1); + + await employerClaim.verifyClaims(userId, latestAdultClaimUserId, latestDegreeClaimUserId); + const verifyResult = await employerClaim.getVerifyClaim(userId); + + const reencryptedVerifyResult = await reencryptEbool( + this.signers, + this.instances, + "alice", + verifyResult, + this.diplomaAddress, + ); + + expect(reencryptedVerifyResult).to.equal(1); + }); + + it("should not allow generating claims without a registered ID", async function () { + // Try to generate degree claim without registering ID first + await expect( + diplomaID.connect(this.signers.alice).generateClaim(this.employerClaimAddress, "generateDegreeClaim(uint256)"), + ).to.be.revertedWithCustomError(idMapping, "NoIdGenerated"); + + // Try to generate adult claim without registering ID first + await expect( + passportID.connect(this.signers.alice).generateClaim(this.employerClaimAddress, "generateAdultClaim(uint256)"), + ).to.be.revertedWithCustomError(idMapping, "NoIdGenerated"); + }); + + it("should not allow generating claims with unregistered diploma/identity", async function () { + // Generate ID but don't register diploma/identity + await idMapping.connect(this.signers.alice).generateId(); + const userId = await idMapping.getId(this.signers.alice); + + // Try to generate degree claim without registering diploma + await expect( + diplomaID.connect(this.signers.alice).generateClaim(this.employerClaimAddress, "generateDegreeClaim(uint256)"), + ).to.be.revertedWith("sender isn't allowed"); + + // Try to generate adult claim without registering identity + await expect( + passportID.connect(this.signers.alice).generateClaim(this.employerClaimAddress, "generateAdultClaim(uint256)"), + ).to.be.revertedWith("sender isn't allowed"); + }); + + it("should allow admin to add a new registrar for diplomaID and passportID", async function () { + // Test diplomaID + await expect(diplomaID.connect(this.signers.alice).addRegistrar(this.signers.bob.address)) + .to.emit(diplomaID, "RoleGranted") + .withArgs(await diplomaID.REGISTRAR_ROLE(), this.signers.bob.address, this.signers.alice.address); + + expect(await diplomaID.hasRole(await diplomaID.REGISTRAR_ROLE(), this.signers.bob.address)).to.be.true; + + // Test passportID + await expect(passportID.connect(this.signers.alice).addRegistrar(this.signers.bob.address)) + .to.emit(passportID, "RoleGranted") + .withArgs(await passportID.REGISTRAR_ROLE(), this.signers.bob.address, this.signers.alice.address); + + expect(await passportID.hasRole(await passportID.REGISTRAR_ROLE(), this.signers.bob.address)).to.be.true; + }); + + it("should allow admin to remove a registrar from diplomaID and passportID", async function () { + // Test diplomaID + await diplomaID.connect(this.signers.alice).addRegistrar(this.signers.bob.address); + await expect(diplomaID.connect(this.signers.alice).removeRegistrar(this.signers.bob.address)) + .to.emit(diplomaID, "RoleRevoked") + .withArgs(await diplomaID.REGISTRAR_ROLE(), this.signers.bob.address, this.signers.alice.address); + + expect(await diplomaID.hasRole(await diplomaID.REGISTRAR_ROLE(), this.signers.bob.address)).to.be.false; + + // Test passportID + await passportID.connect(this.signers.alice).addRegistrar(this.signers.bob.address); + await expect(passportID.connect(this.signers.alice).removeRegistrar(this.signers.bob.address)) + .to.emit(passportID, "RoleRevoked") + .withArgs(await passportID.REGISTRAR_ROLE(), this.signers.bob.address, this.signers.alice.address); + + expect(await passportID.hasRole(await passportID.REGISTRAR_ROLE(), this.signers.bob.address)).to.be.false; + }); + + it("should not allow non-admin to add a registrar to diplomaID and passportID", async function () { + // Test diplomaID + await expect( + diplomaID.connect(this.signers.carol).addRegistrar(this.signers.carol.address), + ).to.be.revertedWithCustomError(diplomaID, "AccessControlUnauthorizedAccount"); + + // Test passportID + await expect( + passportID.connect(this.signers.carol).addRegistrar(this.signers.carol.address), + ).to.be.revertedWithCustomError(passportID, "AccessControlUnauthorizedAccount"); + }); + + it("should not allow non-admin to remove a registrar from diplomaID and passportID", async function () { + // Test diplomaID + await diplomaID.connect(this.signers.alice).addRegistrar(this.signers.bob.address); + await expect( + diplomaID.connect(this.signers.carol).removeRegistrar(this.signers.bob.address), + ).to.be.revertedWithCustomError(diplomaID, "AccessControlUnauthorizedAccount"); + await diplomaID.connect(this.signers.alice).removeRegistrar(this.signers.bob.address); + + // Test passportID + await passportID.connect(this.signers.alice).addRegistrar(this.signers.bob.address); + await expect( + passportID.connect(this.signers.carol).removeRegistrar(this.signers.bob.address), + ).to.be.revertedWithCustomError(passportID, "AccessControlUnauthorizedAccount"); + await passportID.connect(this.signers.alice).removeRegistrar(this.signers.bob.address); + }); +}); diff --git a/contracts/test/decIdentity/fixture/Diploma.fixture.ts b/contracts/test/decIdentity/fixture/Diploma.fixture.ts new file mode 100644 index 0000000..ff0f4ba --- /dev/null +++ b/contracts/test/decIdentity/fixture/Diploma.fixture.ts @@ -0,0 +1,12 @@ +import { ethers } from "hardhat"; + +import type { Diploma, IdMapping } from "../../../types"; +import { getSigners } from "../../signers"; + +export async function deployDiplomaFixture(idMapping: IdMapping): Promise { + const signers = await getSigners(); + const contractFactory = await ethers.getContractFactory("Diploma"); + const contract = await contractFactory.connect(signers.alice).deploy(idMapping); + await contract.waitForDeployment(); + return contract; +} diff --git a/contracts/test/decIdentity/fixture/EmployerClaim.fixture.ts b/contracts/test/decIdentity/fixture/EmployerClaim.fixture.ts new file mode 100644 index 0000000..9e5cd42 --- /dev/null +++ b/contracts/test/decIdentity/fixture/EmployerClaim.fixture.ts @@ -0,0 +1,21 @@ +import { ethers } from "hardhat"; + +import type { Diploma, EmployerClaim, IdMapping, PassportID } from "../../../types"; +import { deployDiplomaFixture } from "./Diploma.fixture"; +import { deployIdMappingFixture } from "./IdMapping.fixture"; +import { deployPassportIDFixture } from "./PassportID.fixture"; + +export async function deployEmployerClaimFixture(): Promise<{ + employerClaim: EmployerClaim; + passportID: PassportID; + diploma: Diploma; + idMapping: IdMapping; +}> { + const idMapping = await deployIdMappingFixture(); + const passportID = await deployPassportIDFixture(idMapping); + const diploma = await deployDiplomaFixture(idMapping); + const EmployerClaimFactory = await ethers.getContractFactory("EmployerClaim"); + const employerClaim = await EmployerClaimFactory.deploy(idMapping, passportID, diploma); + await employerClaim.waitForDeployment(); + return { employerClaim, passportID, diploma, idMapping }; +} diff --git a/contracts/test/decIdentity/fixture/IdMapping.fixture.ts b/contracts/test/decIdentity/fixture/IdMapping.fixture.ts new file mode 100644 index 0000000..2964ae9 --- /dev/null +++ b/contracts/test/decIdentity/fixture/IdMapping.fixture.ts @@ -0,0 +1,13 @@ +import { ethers } from "hardhat"; + +import type { IdMapping } from "../../../types"; +import { getSigners } from "../../signers"; + +export async function deployIdMappingFixture(): Promise { + const signers = await getSigners(); + + const IdMappingFactory = await ethers.getContractFactory("IdMapping"); + const idMapping = await IdMappingFactory.connect(signers.alice).deploy(); + await idMapping.waitForDeployment(); + return idMapping; +} diff --git a/contracts/test/decIdentity/fixture/PassportID.fixture.ts b/contracts/test/decIdentity/fixture/PassportID.fixture.ts new file mode 100644 index 0000000..3657eb2 --- /dev/null +++ b/contracts/test/decIdentity/fixture/PassportID.fixture.ts @@ -0,0 +1,12 @@ +import { ethers } from "hardhat"; + +import type { IdMapping, PassportID } from "../../../types"; +import { getSigners } from "../../signers"; + +export async function deployPassportIDFixture(idMapping: IdMapping): Promise { + const signers = await getSigners(); + const contractFactory = await ethers.getContractFactory("PassportID"); + const contract = await contractFactory.connect(signers.alice).deploy(idMapping); + await contract.waitForDeployment(); + return contract; +} diff --git a/contracts/test/decIdentity/idMapping.ts b/contracts/test/decIdentity/idMapping.ts new file mode 100644 index 0000000..6d7a25e --- /dev/null +++ b/contracts/test/decIdentity/idMapping.ts @@ -0,0 +1,106 @@ +import { expect } from "chai"; +import { ethers } from "hardhat"; + +import type { IdMapping } from "../../types"; +import { createInstance } from "../instance"; +import { getSigners, initSigners } from "../signers"; +import { deployIdMappingFixture } from "./fixture/IdMapping.fixture"; + +describe("IdMapping Contract", function () { + let idMapping: IdMapping; + + before(async function () { + await initSigners(); + this.signers = await getSigners(); + }); + + beforeEach(async function () { + // Deploy the contract + idMapping = await deployIdMappingFixture(); + this.idMappingAddress = await idMapping.getAddress(); + + // Set up accounts + this.instances = await createInstance(); + }); + + it("Should set the ID for an address", async function () { + // Set ID for addr1 + await idMapping.generateId(); + + // Check if the ID was set correctly + expect(await idMapping.getId(this.signers.alice)).to.equal(1); + }); + + it("Should set IDs for multiple addresses", async function () { + // Set IDs for addr1 and addr2 + await idMapping.connect(this.signers.alice).generateId(); + await idMapping.connect(this.signers.bob).generateId(); + + // Verify each address has the correct ID + expect(await idMapping.getId(this.signers.alice)).to.equal(1); + expect(await idMapping.getId(this.signers.bob)).to.equal(2); + }); + + it("Should retrieve address for a given ID", async function () { + // Generate ID for alice + await idMapping.connect(this.signers.alice).generateId(); + + // Get alice's address using their ID (1) + const retrievedAddress = await idMapping.getAddr(1); + expect(retrievedAddress).to.equal(await this.signers.alice.getAddress()); + + // Verify getting an invalid ID reverts + await expect(idMapping.getAddr(999)).to.be.revertedWithCustomError(idMapping, "InvalidId"); + }); + + it("Should not allow generating multiple IDs for same address", async function () { + await idMapping.connect(this.signers.alice).generateId(); + await expect(idMapping.connect(this.signers.alice).generateId()).to.be.revertedWithCustomError( + idMapping, + "IdAlreadyGenerated", + ); + }); + + it("Should fail when getting ID for zero address", async function () { + await expect(idMapping.getId(ethers.ZeroAddress)).to.be.revertedWithCustomError(idMapping, "InvalidAddress"); + }); + + it("Should fail when getting ID for unregistered address", async function () { + await expect(idMapping.getId(this.signers.alice.address)).to.be.revertedWithCustomError(idMapping, "NoIdGenerated"); + }); + + it("Should fail when getting address for invalid ID", async function () { + await expect(idMapping.getAddr(0)).to.be.revertedWithCustomError(idMapping, "InvalidId"); + + await expect(idMapping.getAddr(999)).to.be.revertedWithCustomError(idMapping, "InvalidId"); + }); + + it("Should allow owner to reset ID for an address", async function () { + // Generate ID first + await idMapping.connect(this.signers.alice).generateId(); + const userId = await idMapping.getId(this.signers.alice.address); + + // Reset ID + await idMapping.resetIdForAddress(this.signers.alice.address); + + // Verify ID is reset + await expect(idMapping.getId(this.signers.alice.address)).to.be.revertedWithCustomError(idMapping, "NoIdGenerated"); + + await expect(idMapping.getAddr(userId)).to.be.revertedWithCustomError(idMapping, "NoAddressFound"); + }); + + it("Should not allow non-owner to reset ID", async function () { + await idMapping.connect(this.signers.alice).generateId(); + + await expect( + idMapping.connect(this.signers.bob).resetIdForAddress(this.signers.alice.address), + ).to.be.revertedWithCustomError(idMapping, "OwnableUnauthorizedAccount"); + }); + + it("Should not allow resetting ID for unregistered address", async function () { + await expect(idMapping.resetIdForAddress(this.signers.alice.address)).to.be.revertedWithCustomError( + idMapping, + "NoIdGenerated", + ); + }); +}); diff --git a/contracts/test/decIdentity/passportID.ts b/contracts/test/decIdentity/passportID.ts new file mode 100644 index 0000000..abdf93b --- /dev/null +++ b/contracts/test/decIdentity/passportID.ts @@ -0,0 +1,164 @@ +import "@nomicfoundation/hardhat-chai-matchers"; +import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers"; +import { toBufferBE } from "bigint-buffer"; +import { expect } from "chai"; +import type { FhevmInstance } from "fhevmjs"; + +import type { Diploma, EmployerClaim, IdMapping, PassportID } from "../../types"; +import { createInstance } from "../instance"; +import { reencryptEbool, reencryptEbytes64, reencryptEuint8 } from "../reencrypt"; +import { getSigners, initSigners } from "../signers"; +import { bigIntToBytes64 } from "../utils"; +import { deployEmployerClaimFixture } from "./fixture/EmployerClaim.fixture"; + +// Helper function to convert bigint to bytes +export const bigIntToBytes256 = (value: bigint) => { + return new Uint8Array(toBufferBE(value, 256)); +}; + +describe("PassportID", function () { + let passportID: PassportID; + let employerClaim: EmployerClaim; + let diplomaID: Diploma; + let idMapping: IdMapping; + + // Initialize signers before running tests + before(async function () { + await initSigners(); + this.signers = await getSigners(); + }); + + // Deploy fresh contract instances before each test + beforeEach(async function () { + const deployment = await deployEmployerClaimFixture(); + employerClaim = deployment.employerClaim; + passportID = deployment.passportID; + diplomaID = deployment.diploma; + idMapping = deployment.idMapping; + + this.employerClaimAddress = await employerClaim.getAddress(); + this.diplomaAddress = await diplomaID.getAddress(); + this.passportIDAddress = await passportID.getAddress(); + this.idMappingAddress = await idMapping.getAddress(); + + this.instances = await createInstance(); + }); + + // Helper function to register identity + async function registerIdentity( + userId: bigint, + instance: FhevmInstance, + passportAddress: string, + signer: HardhatEthersSigner, + biodata = bigIntToBytes64(8n), + firstname = bigIntToBytes64(8n), + lastname = bigIntToBytes64(8n), + birthdate = 946681200n, // Sat Jan 01 2000 - 24 years old + ) { + const input = instance.createEncryptedInput(passportAddress, signer.address); + const encryptedData = await input + .addBytes64(biodata) + .addBytes64(firstname) + .addBytes64(lastname) + .add64(birthdate) + .encrypt(); + + await passportID + .connect(signer) + .registerIdentity( + userId, + encryptedData.handles[0], + encryptedData.handles[1], + encryptedData.handles[2], + encryptedData.handles[3], + encryptedData.inputProof, + ); + } + + // Helper function to setup reencryption + async function setupReencryption(instance: FhevmInstance, signer: HardhatEthersSigner, contractAddress: string) { + const { publicKey, privateKey } = instance.generateKeypair(); + const eip712 = instance.createEIP712(publicKey, contractAddress); + const signature = await signer.signTypedData(eip712.domain, { Reencrypt: eip712.types.Reencrypt }, eip712.message); + + return { publicKey, privateKey, signature: signature.replace("0x", "") }; + } + + // Test case: Register an identity successfully + it("should register an identity successfully", async function () { + await idMapping.connect(this.signers.alice).generateId(); + const userId = await idMapping.getId(this.signers.alice); + + await registerIdentity(userId, this.instances, this.passportIDAddress, this.signers.alice); + + expect(await passportID.registered(this.signers.alice.address)); + }); + + // Test case: Prevent duplicate registration for the same user + it("should prevent duplicate registration for the same user", async function () { + await idMapping.connect(this.signers.alice).generateId(); + const userId = await idMapping.getId(this.signers.alice); + + await registerIdentity(userId, this.instances, this.passportIDAddress, this.signers.alice); + + await expect( + registerIdentity(userId, this.instances, this.passportIDAddress, this.signers.alice), + ).to.be.revertedWithCustomError(passportID, "AlreadyRegistered"); + }); + + // Test case: Retrieve the registered identity + it("should retrieve the registered identity", async function () { + await idMapping.connect(this.signers.alice).generateId(); + const userId = await idMapping.getId(this.signers.alice); + + await registerIdentity(userId, this.instances, this.passportIDAddress, this.signers.alice); + + const firstnameHandleAlice = await passportID.getMyIdentityFirstname(userId); + + const reencryptedFirstname = await reencryptEbytes64( + this.signers, + this.instances, + "alice", + firstnameHandleAlice, + this.diplomaAddress, + ); + + expect(reencryptedFirstname).to.equal(8); + }); + + // Test case: Generate an adult claim + it.only("should generate an adult claim", async function () { + await idMapping.connect(this.signers.alice).generateId(); + const userId = await idMapping.getId(this.signers.alice); + + await registerIdentity(userId, this.instances, this.passportIDAddress, this.signers.alice); + + const tx = await passportID + .connect(this.signers.alice) + .generateClaim(this.employerClaimAddress, "generateAdultClaim(uint256)"); + + await expect(tx).to.emit(employerClaim, "AdultClaimGenerated"); + + const latestClaimUserId = await employerClaim.lastClaimId(); + const adultsClaim = await employerClaim.getAdultClaim(latestClaimUserId); + const reencrypted = await reencryptEbool(this.signers, this.instances, "bob", adultsClaim, this.diplomaAddress); + + expect(reencrypted).to.equal(1); + }); + + // Test case: Should fail verification with invalid claim IDs + it("should fail verification with invalid claim IDs", async function () { + await idMapping.connect(this.signers.alice).generateId(); + const userId = await idMapping.getId(this.signers.alice); + + await expect(employerClaim.connect(this.signers.alice).verifyClaims(userId, 0, 1)).to.be.revertedWithCustomError( + employerClaim, + "InvalidClaimId", + ); + + await expect(employerClaim.connect(this.signers.alice).verifyClaims(userId, 1, 0)).to.be.revertedWithCustomError( + employerClaim, + "InvalidClaimId", + ); + }); +}); From 565d1d31c285c0baa9f256c6f79c169b1d01bdbe Mon Sep 17 00:00:00 2001 From: Aurora Poppyseed <30662672+poppyseedDev@users.noreply.github.com> Date: Fri, 13 Dec 2024 18:34:41 -0300 Subject: [PATCH 4/6] adding the frontend template from react-examples --- hardhat/.czrc | 3 + hardhat/.editorconfig | 16 + hardhat/.env.example | 3 + hardhat/.github/workflows/ci.yml | 51 + hardhat/.gitignore | 31 + hardhat/.gitpod.yml | 10 + hardhat/.prettierignore | 22 + hardhat/.prettierrc.yml | 23 + hardhat/.solcover.js | 11 + hardhat/.solhint.json | 24 + hardhat/.solhintignore | 3 + hardhat/.vscode/extensions.json | 3 + hardhat/.vscode/settings.json | 6 + hardhat/CustomProvider.ts | 56 ++ hardhat/LICENSE.md | 16 + hardhat/README.md | 210 ++++ hardhat/contracts/MyConfidentialERC20.sol | 46 + .../contracts/confidentialCounter/sample1.sol | 31 + .../contracts/confidentialCounter/sample2.sol | 26 + .../contracts/confidentialCounter/sample3.sol | 51 + .../contracts/confidentialCounter/sample4.sol | 31 + hardhat/contracts/decIdentity/Diploma.sol | 214 +++++ .../contracts/decIdentity/EmployerClaim.sol | 207 ++++ hardhat/contracts/decIdentity/IdMapping.sol | 114 +++ hardhat/contracts/decIdentity/PassportID.sol | 243 +++++ hardhat/deploy/deploy.ts | 32 + hardhat/eslint.config.mjs | 17 + hardhat/hardhat.config.ts | 154 +++ hardhat/mockedServices/asyncDecrypt.ts | 157 +++ hardhat/mockedServices/coprocessorUtils.ts | 583 ++++++++++++ hardhat/mockedServices/server.ts | 418 ++++++++ hardhat/package.json | 100 ++ hardhat/tasks/accounts.ts | 39 + hardhat/tasks/etherscanVerify.ts | 65 ++ hardhat/tasks/mintMyConfidentialERC20.ts | 18 + hardhat/test/asyncDecrypt.ts | 227 +++++ hardhat/test/confidentialCounter/sample1.ts | 25 + hardhat/test/confidentialCounter/sample2.ts | 30 + hardhat/test/confidentialCounter/sample3.ts | 43 + hardhat/test/confidentialCounter/sample4.ts | 69 ++ .../ConfidentialERC20.fixture.ts | 14 + .../confidentialERC20/ConfidentialERC20.ts | 217 +++++ hardhat/test/constants.ts | 10 + hardhat/test/coprocessorUtils.ts | 901 ++++++++++++++++++ hardhat/test/decIdentity/diploma.ts | 346 +++++++ .../decIdentity/fixture/Diploma.fixture.ts | 12 + .../fixture/EmployerClaim.fixture.ts | 21 + .../decIdentity/fixture/IdMapping.fixture.ts | 13 + .../decIdentity/fixture/PassportID.fixture.ts | 12 + hardhat/test/decIdentity/idMapping.ts | 106 +++ hardhat/test/decIdentity/passportID.ts | 163 ++++ hardhat/test/fhevmjsMocked.ts | 533 +++++++++++ hardhat/test/instance.ts | 30 + hardhat/test/mockedSetup.ts | 56 ++ hardhat/test/operatorPrices.json | 218 +++++ hardhat/test/reencrypt.ts | 179 ++++ hardhat/test/signers.ts | 26 + hardhat/test/utils.ts | 317 ++++++ hardhat/tsconfig.json | 22 + 59 files changed, 6624 insertions(+) create mode 100644 hardhat/.czrc create mode 100644 hardhat/.editorconfig create mode 100644 hardhat/.env.example create mode 100644 hardhat/.github/workflows/ci.yml create mode 100644 hardhat/.gitignore create mode 100644 hardhat/.gitpod.yml create mode 100644 hardhat/.prettierignore create mode 100644 hardhat/.prettierrc.yml create mode 100644 hardhat/.solcover.js create mode 100644 hardhat/.solhint.json create mode 100644 hardhat/.solhintignore create mode 100644 hardhat/.vscode/extensions.json create mode 100644 hardhat/.vscode/settings.json create mode 100644 hardhat/CustomProvider.ts create mode 100644 hardhat/LICENSE.md create mode 100644 hardhat/README.md create mode 100644 hardhat/contracts/MyConfidentialERC20.sol create mode 100644 hardhat/contracts/confidentialCounter/sample1.sol create mode 100644 hardhat/contracts/confidentialCounter/sample2.sol create mode 100644 hardhat/contracts/confidentialCounter/sample3.sol create mode 100644 hardhat/contracts/confidentialCounter/sample4.sol create mode 100644 hardhat/contracts/decIdentity/Diploma.sol create mode 100644 hardhat/contracts/decIdentity/EmployerClaim.sol create mode 100644 hardhat/contracts/decIdentity/IdMapping.sol create mode 100644 hardhat/contracts/decIdentity/PassportID.sol create mode 100644 hardhat/deploy/deploy.ts create mode 100644 hardhat/eslint.config.mjs create mode 100644 hardhat/hardhat.config.ts create mode 100644 hardhat/mockedServices/asyncDecrypt.ts create mode 100644 hardhat/mockedServices/coprocessorUtils.ts create mode 100644 hardhat/mockedServices/server.ts create mode 100644 hardhat/package.json create mode 100644 hardhat/tasks/accounts.ts create mode 100644 hardhat/tasks/etherscanVerify.ts create mode 100644 hardhat/tasks/mintMyConfidentialERC20.ts create mode 100644 hardhat/test/asyncDecrypt.ts create mode 100644 hardhat/test/confidentialCounter/sample1.ts create mode 100644 hardhat/test/confidentialCounter/sample2.ts create mode 100644 hardhat/test/confidentialCounter/sample3.ts create mode 100644 hardhat/test/confidentialCounter/sample4.ts create mode 100644 hardhat/test/confidentialERC20/ConfidentialERC20.fixture.ts create mode 100644 hardhat/test/confidentialERC20/ConfidentialERC20.ts create mode 100644 hardhat/test/constants.ts create mode 100644 hardhat/test/coprocessorUtils.ts create mode 100644 hardhat/test/decIdentity/diploma.ts create mode 100644 hardhat/test/decIdentity/fixture/Diploma.fixture.ts create mode 100644 hardhat/test/decIdentity/fixture/EmployerClaim.fixture.ts create mode 100644 hardhat/test/decIdentity/fixture/IdMapping.fixture.ts create mode 100644 hardhat/test/decIdentity/fixture/PassportID.fixture.ts create mode 100644 hardhat/test/decIdentity/idMapping.ts create mode 100644 hardhat/test/decIdentity/passportID.ts create mode 100644 hardhat/test/fhevmjsMocked.ts create mode 100644 hardhat/test/instance.ts create mode 100644 hardhat/test/mockedSetup.ts create mode 100644 hardhat/test/operatorPrices.json create mode 100644 hardhat/test/reencrypt.ts create mode 100644 hardhat/test/signers.ts create mode 100644 hardhat/test/utils.ts create mode 100644 hardhat/tsconfig.json diff --git a/hardhat/.czrc b/hardhat/.czrc new file mode 100644 index 0000000..d1bcc20 --- /dev/null +++ b/hardhat/.czrc @@ -0,0 +1,3 @@ +{ + "path": "cz-conventional-changelog" +} diff --git a/hardhat/.editorconfig b/hardhat/.editorconfig new file mode 100644 index 0000000..6fd96c1 --- /dev/null +++ b/hardhat/.editorconfig @@ -0,0 +1,16 @@ +# EditorConfig http://EditorConfig.org + +# top-most EditorConfig file +root = true + +# All files +[*] +charset = utf-8 +end_of_line = lf +indent_size = 2 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true + +[*.sol] +indent_size = 4 diff --git a/hardhat/.env.example b/hardhat/.env.example new file mode 100644 index 0000000..df1dbe0 --- /dev/null +++ b/hardhat/.env.example @@ -0,0 +1,3 @@ +export MNEMONIC="exchange vintage ocean narrow danger return culture ignore trim solve clock hidden buddy wise emotion" +export SEPOLIA_RPC_URL="https://sepolia.infura.io/v3/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +export ETHERSCAN_API_KEY="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \ No newline at end of file diff --git a/hardhat/.github/workflows/ci.yml b/hardhat/.github/workflows/ci.yml new file mode 100644 index 0000000..0fabbfc --- /dev/null +++ b/hardhat/.github/workflows/ci.yml @@ -0,0 +1,51 @@ +name: "CI" + +env: + DOTENV_CONFIG_PATH: "./.env.example" + +on: + workflow_dispatch: + pull_request: + push: + branches: + - main + +jobs: + ci: + runs-on: "ubuntu-latest" + steps: + - name: "Check out the repo" + uses: "actions/checkout@v3" + + - name: "Install Pnpm" + uses: "pnpm/action-setup@v2" + with: + version: "8" + + - name: "Install Node.js" + uses: "actions/setup-node@v3" + with: + cache: "pnpm" + node-version: "lts/*" + + - name: "Install the dependencies" + run: "pnpm install" + + - name: "Lint the code" + run: "pnpm lint" + + - name: "Add lint summary" + run: | + echo "## Lint results" >> $GITHUB_STEP_SUMMARY + echo "✅ Passed" >> $GITHUB_STEP_SUMMARY + + - name: "Compile the contracts and generate the TypeChain bindings" + run: "pnpm typechain" + + - name: "Test the contracts and generate the coverage report" + run: "pnpm coverage:mock" + + - name: "Add test summary" + run: | + echo "## Test results" >> $GITHUB_STEP_SUMMARY + echo "✅ Passed" >> $GITHUB_STEP_SUMMARY diff --git a/hardhat/.gitignore b/hardhat/.gitignore new file mode 100644 index 0000000..7aedbca --- /dev/null +++ b/hardhat/.gitignore @@ -0,0 +1,31 @@ +# directories +.coverage_artifacts +.coverage_cache +.coverage_contracts +artifacts +build +cache +coverage +dist +node_modules +types +deployments +kms-fhe-keys/ +network-fhe-keys/ +fhevmTemp/ +abi/ + +# files +*.env +*.log +.env.docker +.DS_Store +.pnp.* +coverage.json +package-lock.json +yarn.lock + +res/ +running_node/ + +sql.db diff --git a/hardhat/.gitpod.yml b/hardhat/.gitpod.yml new file mode 100644 index 0000000..dd2444f --- /dev/null +++ b/hardhat/.gitpod.yml @@ -0,0 +1,10 @@ +image: "gitpod/workspace-node:latest" + +tasks: + - init: "pnpm install" + +vscode: + extensions: + - "esbenp.prettier-vscode" + - "NomicFoundation.hardhat-solidity" + - "ritwickdey.LiveServer" diff --git a/hardhat/.prettierignore b/hardhat/.prettierignore new file mode 100644 index 0000000..d1401c9 --- /dev/null +++ b/hardhat/.prettierignore @@ -0,0 +1,22 @@ +# directories +.coverage_artifacts +.coverage_cache +.coverage_contracts +artifacts +build +cache +coverage +dist +node_modules +types + +# files +*.env +*.log +.DS_Store +.pnp.* +coverage.json +package-lock.json +pnpm-lock.yaml +yarn.lock +README.md \ No newline at end of file diff --git a/hardhat/.prettierrc.yml b/hardhat/.prettierrc.yml new file mode 100644 index 0000000..56221e3 --- /dev/null +++ b/hardhat/.prettierrc.yml @@ -0,0 +1,23 @@ +bracketSpacing: true +plugins: + - "@trivago/prettier-plugin-sort-imports" + - "prettier-plugin-solidity" +printWidth: 120 +proseWrap: "always" +singleQuote: false +tabWidth: 2 +trailingComma: "all" + +overrides: + - files: "*.sol" + options: + compiler: "0.8.24" + parser: "solidity-parse" + tabWidth: 4 + - files: "*.ts" + options: + importOrder: ["", "^[./]"] + importOrderParserPlugins: ["typescript"] + importOrderSeparation: true + importOrderSortSpecifiers: true + parser: "typescript" diff --git a/hardhat/.solcover.js b/hardhat/.solcover.js new file mode 100644 index 0000000..938b911 --- /dev/null +++ b/hardhat/.solcover.js @@ -0,0 +1,11 @@ +module.exports = { + istanbulReporter: ["html", "lcov"], + providerOptions: { + mnemonic: process.env.MNEMONIC, + }, + skipFiles: ["test", "fhevmTemp"], + mocha: { + fgrep: "[skip-on-coverage]", + invert: true, + }, +}; diff --git a/hardhat/.solhint.json b/hardhat/.solhint.json new file mode 100644 index 0000000..826fe4e --- /dev/null +++ b/hardhat/.solhint.json @@ -0,0 +1,24 @@ +{ + "extends": "solhint:recommended", + "plugins": ["prettier"], + "rules": { + "const-name-snakecase": "off", + "no-global-import": "off", + "reason-string": "off", + "state-visibility": "off", + "custom-errors": "off", + "code-complexity": ["error", 8], + "compiler-version": ["error", ">=0.8.4"], + "func-visibility": ["error", { "ignoreConstructors": true }], + "max-line-length": ["error", 120], + "named-parameters-mapping": "off", + "no-console": "off", + "not-rely-on-time": "off", + "prettier/prettier": [ + "error", + { + "endOfLine": "auto" + } + ] + } +} diff --git a/hardhat/.solhintignore b/hardhat/.solhintignore new file mode 100644 index 0000000..16dc0c0 --- /dev/null +++ b/hardhat/.solhintignore @@ -0,0 +1,3 @@ +# directories +**/artifacts +**/node_modules diff --git a/hardhat/.vscode/extensions.json b/hardhat/.vscode/extensions.json new file mode 100644 index 0000000..9a51b72 --- /dev/null +++ b/hardhat/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["esbenp.prettier-vscode", "NomicFoundation.hardhat-solidity"] +} diff --git a/hardhat/.vscode/settings.json b/hardhat/.vscode/settings.json new file mode 100644 index 0000000..9fe44aa --- /dev/null +++ b/hardhat/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true, + "prettier.documentSelectors": ["**/*.sol"], + "solidity.formatter": "prettier" +} diff --git a/hardhat/CustomProvider.ts b/hardhat/CustomProvider.ts new file mode 100644 index 0000000..d48f2f4 --- /dev/null +++ b/hardhat/CustomProvider.ts @@ -0,0 +1,56 @@ +import { ProviderWrapper } from "hardhat/plugins"; +import type { EIP1193Provider, RequestArguments } from "hardhat/types"; + +interface Test { + request: EIP1193Provider["request"]; +} + +class CustomProvider extends ProviderWrapper implements Test { + public lastBlockSnapshot: number; + public lastCounterRand: number; + public lastBlockSnapshotForDecrypt: number; + + constructor(protected readonly _wrappedProvider: EIP1193Provider) { + super(_wrappedProvider); + this.lastBlockSnapshot = 0; // Initialize the variable + this.lastCounterRand = 0; + this.lastBlockSnapshotForDecrypt = 0; + } + + async request(args: RequestArguments): ReturnType { + if (args.method === "evm_revert") { + const result = await this._wrappedProvider.request(args); + const blockNumberHex = (await this._wrappedProvider.request({ method: "eth_blockNumber" })) as string; + this.lastBlockSnapshot = parseInt(blockNumberHex); + this.lastBlockSnapshotForDecrypt = parseInt(blockNumberHex); + + const callData = { + to: "0x000000000000000000000000000000000000005d", + data: "0x1f20d85c", + }; + this.lastCounterRand = (await this._wrappedProvider.request({ + method: "eth_call", + params: [callData, "latest"], + })) as number; + return result; + } + if (args.method === "get_lastBlockSnapshot") { + return [this.lastBlockSnapshot, this.lastCounterRand]; + } + if (args.method === "get_lastBlockSnapshotForDecrypt") { + return this.lastBlockSnapshotForDecrypt; + } + if (args.method === "set_lastBlockSnapshot") { + this.lastBlockSnapshot = Array.isArray(args.params!) && args.params[0]; + return this.lastBlockSnapshot; + } + if (args.method === "set_lastBlockSnapshotForDecrypt") { + this.lastBlockSnapshotForDecrypt = Array.isArray(args.params!) && args.params[0]; + return this.lastBlockSnapshotForDecrypt; + } + const result = this._wrappedProvider.request(args); + return result; + } +} + +export default CustomProvider; diff --git a/hardhat/LICENSE.md b/hardhat/LICENSE.md new file mode 100644 index 0000000..88a2b87 --- /dev/null +++ b/hardhat/LICENSE.md @@ -0,0 +1,16 @@ +MIT License + +Copyright (c) 2023 Paul Razvan Berg + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit +persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the +Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/hardhat/README.md b/hardhat/README.md new file mode 100644 index 0000000..ea4d0eb --- /dev/null +++ b/hardhat/README.md @@ -0,0 +1,210 @@ +# Hardhat Template [![Open in Gitpod][gitpod-badge]][gitpod] [![Github Actions][gha-badge]][gha] [![Hardhat][hardhat-badge]][hardhat] [![License: MIT][license-badge]][license] + +[gitpod]: https://gitpod.io/#https://github.com/zama-ai/fhevm-hardhat-template +[gitpod-badge]: https://img.shields.io/badge/Gitpod-Open%20in%20Gitpod-FFB45B?logo=gitpod +[gha]: https://github.com/zama-ai/fhevm-hardhat-template/actions +[gha-badge]: https://github.com/zama-ai/fhevm-hardhat-template/actions/workflows/ci.yml/badge.svg +[hardhat]: https://hardhat.org/ +[hardhat-badge]: https://img.shields.io/badge/Built%20with-Hardhat-FFDB1C.svg +[license]: https://opensource.org/licenses/MIT +[license-badge]: https://img.shields.io/badge/License-MIT-blue.svg + +A Hardhat-based template for developing Solidity smart contracts, with sensible defaults. + +- [Hardhat](https://github.com/nomiclabs/hardhat): compile, run and test smart contracts +- [TypeChain](https://github.com/ethereum-ts/TypeChain): generate TypeScript bindings for smart contracts +- [Ethers](https://github.com/ethers-io/ethers.js/): renowned Ethereum library and wallet implementation +- [Solhint](https://github.com/protofire/solhint): code linter +- [Solcover](https://github.com/sc-forks/solidity-coverage): code coverage +- [Prettier Plugin Solidity](https://github.com/prettier-solidity/prettier-plugin-solidity): code formatter + +## Getting Started + +Click the [`Use this template`](https://github.com/zama-ai/fhevm-hardhat-template/generate) button at the top of the +page to create a new repository with this repo as the initial state. + +## Features + +This template builds upon the frameworks and libraries mentioned above, so for details about their specific features, +please consult their respective documentations. + +For example, for Hardhat, you can refer to the [Hardhat Tutorial](https://hardhat.org/tutorial) and the +[Hardhat Docs](https://hardhat.org/docs). You might be in particular interested in reading the +[Testing Contracts](https://hardhat.org/tutorial/testing-contracts) section. + +### Sensible Defaults + +This template comes with sensible default configurations in the following files: + +```text +├── .editorconfig +├── .eslintignore +├── .eslintrc.yml +├── .gitignore +├── .prettierignore +├── .prettierrc.yml +├── .solcover.js +├── .solhint.json +└── hardhat.config.ts +``` + +### VSCode Integration + +This template is IDE agnostic, but for the best user experience, you may want to use it in VSCode alongside Nomic +Foundation's [Solidity extension](https://marketplace.visualstudio.com/items?itemName=NomicFoundation.hardhat-solidity). + +### GitHub Actions + +This template comes with GitHub Actions pre-configured. Your contracts will be linted and tested on every push and pull +request made to the `main` branch. + +Note though that to make this work, you must use your `INFURA_API_KEY` and your `MNEMONIC` as GitHub secrets. + +You can edit the CI script in [.github/workflows/ci.yml](./.github/workflows/ci.yml). + +## Usage + +### Pre Requisites + +Before being able to run any command, you need to create a `.env` file and set a BIP-39 compatible mnemonic as the `MNEMONIC` +environment variable. You can follow the example in `.env.example` or start with the following command: + +```sh +cp .env.example .env +``` + +If you don't already have a mnemonic, you can use this [website](https://iancoleman.io/bip39/) to generate one. An alternative, if you have [foundry](https://book.getfoundry.sh/getting-started/installation) installed is to use the `cast wallet new-mnemonic` command. + +Then, install all needed dependencies - please **_make sure to use Node v20_** or more recent: + +```sh +npm install +``` + +### Compile + +Compile the smart contracts with Hardhat: + +```sh +npm run compile +``` + +### TypeChain + +Compile the smart contracts and generate TypeChain bindings: + +```sh +npm run typechain +``` + +### Test + +Run the tests with Hardhat - this will run the tests on a local hardhat node in mocked mode (i.e the FHE operations and decryptions will be simulated by default): + +```sh +npm run test +``` + +### Lint Solidity + +Lint the Solidity code: + +```sh +npm run lint:sol +``` + +### Lint TypeScript + +Lint the TypeScript code: + +```sh +npm run lint:ts +``` + + +### Clean + +Delete the smart contract artifacts, the coverage reports and the Hardhat cache: + +```sh +npm run clean +``` + +### Mocked mode + +The mocked mode allows faster testing and the ability to analyze coverage of the tests. In this mocked version, +encrypted types are not really encrypted, and the tests are run on the original version of the EVM, on a local hardhat +network instance. To run the tests in mocked mode, you can use directly the following command: + +```bash +npm run test +``` + +You can still use all the usual specific [hardhat network methods](https://hardhat.org/hardhat-network/docs/reference#hardhat-network-methods), such as `evm_snapshot`, `evm_mine`, `evm_increaseTime`, etc, which are very helpful in a testing context. Another useful hardhat feature, is the [console.log](https://hardhat.org/hardhat-network/docs/reference#console.log) function which can be used in fhevm smart contracts in mocked mode as well. + +To analyze the coverage of the tests (in mocked mode necessarily, as this cannot be done on the real fhEVM node), you +can use this command : + +```bash +npm run coverage +``` + +Then open the file `coverage/index.html`. You can see there which line or branch for each contract which has been +covered or missed by your test suite. This allows increased security by pointing out missing branches not covered yet by +the current tests. + +Finally, a new fhevm-specific feature is available in mocked mode: the `debug.decrypt[XX]` functions, which can decrypt directly any encrypted value. Please refer to the [utils.ts](https://github.com/zama-ai/fhevm/blob/main/test/utils.ts#L87-L317) file for the corresponding documentation. + +> [!Note] +> Due to intrinsic limitations of the original EVM, the mocked version differs in rare edge cases from the real fhEVM, the main difference is the gas consumption for the FHE operations (native gas is around 20% underestimated in mocked mode). This means that before deploying to production, developers should still run the tests with the original fhEVM node, as a final check - i.e in non-mocked mode (see next section). + +### Non-mocked mode - Sepolia + +To run your test on a real fhevm node, you can use the coprocessor deployed on the Sepolia test network. To do this, ensure you are using a valid value `SEPOLIA_RPC_URL` in your `.env` file. You can get free Sepolia RPC URLs by creating an account on services such as [Infura](https://www.infura.io/) or [Alchemy](https://www.alchemy.com/). Then you can use the following command: + +```bash +npx hardhat test [PATH_TO_YOUR_TEST] --network sepolia +``` + +The `--network sepolia` flag will make your test run on a real fhevm coprocessor. Obviously, for the same tests to pass on Sepolia, contrarily to mocked mode, you are not allowed to use any hardhat node specific method, and neither use any of the `debug.decrypt[XX]` functions. + +> [!Note] +> For this test to succeed, first ensure you set your own private `MNEMONIC` variable in the `.env` file and then ensure you have funded your test accounts on Sepolia. For example you can use the following command to get the corresponding private keys associated with the first `5` accounts derived from the mnemonic: +``` +npx hardhat get-accounts --num-accounts 5 +``` +This will let you add them to the Metamask app, to easily fund them from your personal wallet. + +If you don't own already Sepolia test tokens, you can for example use a free faucet such as [https://sepolia-faucet.pk910.de/](https://sepolia-faucet.pk910.de/). + +Another faster way to test the coprocessor on Sepolia is to simply run the following command: +``` +npm run deploy-sepolia +``` +This would automatically make Alice's account deploy an instance of the `MyConfidentialERC20` example contract on Sepolia, and then make Alice mint to herself `10000` tokens. + + +### Etherscan verification + +If you are using a real instance of the fhEVM, you can verify your deployed contracts on the Etherscan explorer. +You first need to set the `ETHERSCAN_API_KEY` variable in the `.env` file to a valid value. You can get such an API key for free by creating an account on the [Etherscan website](https://docs.etherscan.io/getting-started/viewing-api-usage-statistics). + +Then, simply use the `verify-deployed` hardhat task, via this command: +``` +npx hardhat verify-deployed --address [ADDRESS_CONTRACT_TO_VERIFY] --contract [FULL_CONTRACT_PATH] --args "[CONSTRUCTOR_ARGUMENTS_COMMA_SEPARATED]" --network [NETWORK_NAME] +``` +As a concrete example, to verify the deployed `MyConfidentialERC20` from previous section, you can use: +``` +npx hardhat verify-deployed --address [CONFIDENTIAL_ERC20_ADDRESS] --contract contracts/MyConfidentialERC20.sol:MyConfidentialERC20 --args "Naraggara,NARA" --network sepolia +``` + +Note that you should replace the address placeholder `[CONFIDENTIAL_ERC20_ADDRESS]` by the concrete address that is logged when you run the `npm run deploy-sepolia` deployment script. + +### Syntax Highlighting + +If you use VSCode, you can get Solidity syntax highlighting with the +[hardhat-solidity](https://marketplace.visualstudio.com/items?itemName=NomicFoundation.hardhat-solidity) extension. + +## License + +This project is licensed under MIT. diff --git a/hardhat/contracts/MyConfidentialERC20.sol b/hardhat/contracts/MyConfidentialERC20.sol new file mode 100644 index 0000000..d133864 --- /dev/null +++ b/hardhat/contracts/MyConfidentialERC20.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: BSD-3-Clause-Clear + +pragma solidity ^0.8.24; + +import "fhevm/lib/TFHE.sol"; +import "fhevm/config/ZamaFHEVMConfig.sol"; +import "fhevm/config/ZamaGatewayConfig.sol"; +import "fhevm/gateway/GatewayCaller.sol"; +import "fhevm-contracts/contracts/token/ERC20/extensions/ConfidentialERC20Mintable.sol"; + +/// @notice This contract implements an encrypted ERC20-like token with confidential balances using Zama's FHE library. +/// @dev It supports typical ERC20 functionality such as transferring tokens, minting, and setting allowances, +/// @dev but uses encrypted data types. +contract MyConfidentialERC20 is + SepoliaZamaFHEVMConfig, + SepoliaZamaGatewayConfig, + GatewayCaller, + ConfidentialERC20Mintable +{ + // @note `SECRET` is not so secret, since it is trivially encrypted and just to have a decryption test + euint64 internal immutable SECRET; + + // @note `revealedSecret` will hold the decrypted result once the Gateway will relay the decryption of `SECRET` + uint64 public revealedSecret; + + /// @notice Constructor to initialize the token's name and symbol, and set up the owner + /// @param name_ The name of the token + /// @param symbol_ The symbol of the token + constructor(string memory name_, string memory symbol_) ConfidentialERC20Mintable(name_, symbol_, msg.sender) { + SECRET = TFHE.asEuint64(42); + TFHE.allowThis(SECRET); + } + + /// @notice Request decryption of `SECRET` + function requestSecret() public { + uint256[] memory cts = new uint256[](1); + cts[0] = Gateway.toUint256(SECRET); + Gateway.requestDecryption(cts, this.callbackSecret.selector, 0, block.timestamp + 100, false); + } + + /// @notice Callback function for `SECRET` decryption + /// @param `decryptedValue` The decrypted 64-bit unsigned integer + function callbackSecret(uint256, uint64 decryptedValue) public onlyGateway { + revealedSecret = decryptedValue; + } +} diff --git a/hardhat/contracts/confidentialCounter/sample1.sol b/hardhat/contracts/confidentialCounter/sample1.sol new file mode 100644 index 0000000..2730e78 --- /dev/null +++ b/hardhat/contracts/confidentialCounter/sample1.sol @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "fhevm/lib/TFHE.sol"; +import "fhevm/config/ZamaFHEVMConfig.sol"; + +/// @title EncryptedCounter1 +/// @notice A basic contract demonstrating the setup of encrypted types +/// @dev Uses TFHE library for fully homomorphic encryption operations +/// @custom:experimental This is a minimal example contract intended only for learning purposes +/// @custom:notice This contract has limited real-world utility and serves primarily as a starting point +/// for understanding how to implement basic FHE operations in Solidity +contract EncryptedCounter1 is SepoliaZamaFHEVMConfig { + euint8 internal counter; + euint8 internal immutable CONST_ONE; + + constructor() { + // Initialize counter with an encrypted zero value + counter = TFHE.asEuint8(0); + TFHE.allowThis(counter); + // Save on gas by computing the constant here + CONST_ONE = TFHE.asEuint8(1); + TFHE.allowThis(CONST_ONE); + } + + function increment() public { + // Perform encrypted addition to increment the counter + counter = TFHE.add(counter, CONST_ONE); + TFHE.allowThis(counter); + } +} diff --git a/hardhat/contracts/confidentialCounter/sample2.sol b/hardhat/contracts/confidentialCounter/sample2.sol new file mode 100644 index 0000000..d6efd9f --- /dev/null +++ b/hardhat/contracts/confidentialCounter/sample2.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "fhevm/lib/TFHE.sol"; +import "fhevm/config/ZamaFHEVMConfig.sol"; + +/// @title EncryptedCounter2 +/// @notice A contract that maintains an encrypted counter and is meant for demonstrating how to add encrypted types +/// @dev Uses TFHE library for fully homomorphic encryption operations +/// @custom:experimental This contract is experimental and uses FHE technology +contract EncryptedCounter2 is SepoliaZamaFHEVMConfig { + euint8 counter; + + constructor() { + // Initialize counter with an encrypted zero value + counter = TFHE.asEuint8(0); + TFHE.allowThis(counter); + } + + function incrementBy(einput amount, bytes calldata inputProof) public { + // Convert input to euint8 and add to counter + euint8 incrementAmount = TFHE.asEuint8(amount, inputProof); + counter = TFHE.add(counter, incrementAmount); + TFHE.allowThis(counter); + } +} diff --git a/hardhat/contracts/confidentialCounter/sample3.sol b/hardhat/contracts/confidentialCounter/sample3.sol new file mode 100644 index 0000000..3f4708e --- /dev/null +++ b/hardhat/contracts/confidentialCounter/sample3.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "fhevm/lib/TFHE.sol"; +import "fhevm/config/ZamaFHEVMConfig.sol"; +import "fhevm/config/ZamaGatewayConfig.sol"; +import "fhevm/gateway/GatewayCaller.sol"; + +/// @title EncryptedCounter3 +/// @notice A contract that maintains an encrypted counter and is meant for demonstrating how decryption works +/// @dev Uses TFHE library for fully homomorphic encryption operations and Gateway for decryption +/// @custom:experimental This contract is experimental and uses FHE technology with decryption capabilities +contract EncryptedCounter3 is SepoliaZamaFHEVMConfig, SepoliaZamaGatewayConfig, GatewayCaller { + /// @dev Decrypted state variable + euint8 counter; + uint8 public decryptedCounter; + + constructor() { + // Initialize counter with an encrypted zero value + counter = TFHE.asEuint8(0); + TFHE.allowThis(counter); + } + + function incrementBy(einput amount, bytes calldata inputProof) public { + // Convert input to euint8 and add to counter + euint8 incrementAmount = TFHE.asEuint8(amount, inputProof); + counter = TFHE.add(counter, incrementAmount); + TFHE.allowThis(counter); + } + + /// @notice Request decryption of the counter value + function requestDecryptCounter() public { + uint256[] memory cts = new uint256[](1); + cts[0] = Gateway.toUint256(counter); + Gateway.requestDecryption(cts, this.callbackCounter.selector, 0, block.timestamp + 100, false); + } + + /// @notice Callback function for counter decryption + /// @param decryptedInput The decrypted counter value + /// @return The decrypted value + function callbackCounter(uint256, uint8 decryptedInput) public onlyGateway returns (uint8) { + decryptedCounter = decryptedInput; + return decryptedInput; + } + + /// @notice Get the decrypted counter value + /// @return The decrypted counter value + function getDecryptedCounter() public view returns (uint8) { + return decryptedCounter; + } +} diff --git a/hardhat/contracts/confidentialCounter/sample4.sol b/hardhat/contracts/confidentialCounter/sample4.sol new file mode 100644 index 0000000..bcd08f8 --- /dev/null +++ b/hardhat/contracts/confidentialCounter/sample4.sol @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "fhevm/lib/TFHE.sol"; +import "fhevm/config/ZamaFHEVMConfig.sol"; + +/// @title EncryptedCounter4 +/// @notice A contract that maintains encrypted counters for each user and is meant for demonstrating how re-encryption works +/// @dev Uses TFHE library for fully homomorphic encryption operations +/// @custom:security Each user can only access and modify their own counter +/// @custom:experimental This contract is experimental and uses FHE technology +contract EncryptedCounter4 is SepoliaZamaFHEVMConfig { + // Mapping from user address to their encrypted counter value + mapping(address => euint8) private counters; + + function incrementBy(einput amount, bytes calldata inputProof) public { + // Initialize counter if it doesn't exist + counters[msg.sender] = TFHE.asEuint8(0); + + // Convert input to euint8 and add to sender's counter + euint8 incrementAmount = TFHE.asEuint8(amount, inputProof); + counters[msg.sender] = TFHE.add(counters[msg.sender], incrementAmount); + TFHE.allowThis(counters[msg.sender]); + TFHE.allow(counters[msg.sender], msg.sender); + } + + function getCounter() public view returns (euint8) { + // Return the encrypted counter value for the sender + return counters[msg.sender]; + } +} diff --git a/hardhat/contracts/decIdentity/Diploma.sol b/hardhat/contracts/decIdentity/Diploma.sol new file mode 100644 index 0000000..a7fc29d --- /dev/null +++ b/hardhat/contracts/decIdentity/Diploma.sol @@ -0,0 +1,214 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import "fhevm/lib/TFHE.sol"; +import "./IdMapping.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "fhevm/config/ZamaFHEVMConfig.sol"; + +/** + * @title Diploma + * @author ZAMA + * @dev Contract for managing encrypted diploma records using TFHE encryption + * @notice Allows universities to register encrypted diploma data and graduates to generate claims + */ +contract Diploma is SepoliaZamaFHEVMConfig, AccessControl { + /// @dev Constants + bytes32 public constant REGISTRAR_ROLE = keccak256("REGISTRAR_ROLE"); + bytes32 public constant OWNER_ROLE = keccak256("OWNER_ROLE"); + + /// @dev Custom errors + /// @notice Thrown when attempting to register a diploma for a user who already has one + error DiplomaAlreadyRegistered(); + /// @notice Thrown when attempting to access diploma data for a user who doesn't have one registered + error DiplomaNotRegistered(); + /// @notice Thrown when sender doesn't have permission to access the encrypted data + error AccessNotPermitted(); + /// @notice Thrown when claim generation fails, includes failure data + /// @param data The error data returned from the failed claim generation + error ClaimGenerationFailed(bytes data); + + /// @dev Structure to hold encrypted diploma data + struct DiplomaData { + euint64 id; // Encrypted unique diploma ID + ebytes64 university; // Encrypted university identifier + euint16 degree; // Encrypted degree identifier + ebytes64 grade; // Encrypted grade + } + + /// @dev Instance of IdMapping contract + IdMapping private idMapping; + + /// @dev Mapping to store diploma records by user ID + mapping(uint256 => DiplomaData) private diplomaRecords; + /// @dev Mapping to track registered diplomas + mapping(uint256 => bool) public registered; + /// @dev Mapping for degree identifiers to degree names + mapping(uint16 => string) public degreeTypes; + + /// @dev Event emitted when a diploma is registered + event DiplomaRegistered(address indexed graduate); + /// @dev Event emitted when a claim is generated + event ClaimGenerated(address indexed graduate, address claimAddress, string claimFn); + + /** + * @dev Constructor to initialize the contract with IdMapping address + * @param _idMappingAddress Address of the IdMapping contract + */ + constructor(address _idMappingAddress) { + idMapping = IdMapping(_idMappingAddress); + _grantRole(OWNER_ROLE, msg.sender); // Admin role for contract owner + _grantRole(REGISTRAR_ROLE, msg.sender); // Registrar role for contract owner + + // Initialize degree mappings + degreeTypes[1] = "Electrical Engineering (B.Eng)"; + degreeTypes[2] = "Mechanical Engineering (B.Eng)"; + degreeTypes[3] = "Computer Science (B.Sc)"; + degreeTypes[4] = "Civil Engineering (B.Eng)"; + degreeTypes[5] = "Chemical Engineering (B.Eng)"; + // Graduate degrees start from 1001 + degreeTypes[1001] = "Electrical Engineering (M.Eng)"; + degreeTypes[1002] = "Mechanical Engineering (M.Eng)"; + degreeTypes[1003] = "Computer Science (M.Sc)"; + // Doctoral degrees start from 2001 + degreeTypes[2001] = "Electrical Engineering (Ph.D)"; + degreeTypes[2002] = "Computer Science (Ph.D)"; + } + + /** + * @dev Adds a new registrar address + * @param registrar Address to be granted registrar role + */ + function addRegistrar(address registrar) external onlyRole(OWNER_ROLE) { + _grantRole(REGISTRAR_ROLE, registrar); + } + + /** + * @dev Removes a registrar address + * @param registrar Address to be revoked registrar role + */ + function removeRegistrar(address registrar) external onlyRole(OWNER_ROLE) { + _revokeRole(REGISTRAR_ROLE, registrar); + } + + /** + * @dev Retrieves the degree type for a given degree ID + * @param degreeId The ID of the degree type to retrieve + * @return The name/description of the degree type + */ + function getDegreeType(uint16 degreeId) public view returns (string memory) { + return degreeTypes[degreeId]; + } + + /** + * @dev Registers a new encrypted diploma for a user + * @param userId ID of the user to register diploma for + * @param university Encrypted university identifier + * @param degree Encrypted degree type + * @param grade Encrypted grade + * @param inputProof Proof for encrypted inputs + * @return bool indicating success + */ + function registerDiploma( + uint256 userId, + einput university, + einput degree, + einput grade, + bytes calldata inputProof + ) public virtual onlyRole(REGISTRAR_ROLE) returns (bool) { + if (registered[userId]) revert DiplomaAlreadyRegistered(); + + // Generate a new encrypted diploma ID + euint64 newId = TFHE.randEuint64(); + + // Store the encrypted diploma data + diplomaRecords[userId] = DiplomaData({ + id: newId, + university: TFHE.asEbytes64(university, inputProof), + degree: TFHE.asEuint16(degree, inputProof), + grade: TFHE.asEbytes64(grade, inputProof) + }); + + registered[userId] = true; // Mark the diploma as registered + + // Get the address associated with the user ID + address addressToBeAllowed = idMapping.getAddr(userId); + + // Allow the graduate to access their own data + TFHE.allow(diplomaRecords[userId].id, addressToBeAllowed); + TFHE.allow(diplomaRecords[userId].university, addressToBeAllowed); + TFHE.allow(diplomaRecords[userId].degree, addressToBeAllowed); + TFHE.allow(diplomaRecords[userId].grade, addressToBeAllowed); + + // Allow the contract to access the data + TFHE.allowThis(diplomaRecords[userId].id); + TFHE.allowThis(diplomaRecords[userId].university); + TFHE.allowThis(diplomaRecords[userId].degree); + TFHE.allowThis(diplomaRecords[userId].grade); + + emit DiplomaRegistered(addressToBeAllowed); // Emit event for diploma registration + + return true; + } + + /** + * @dev Retrieves encrypted university identifier for a user + * @param userId ID of the user to get university for + * @return euint8 Encrypted university identifier + */ + function getMyUniversity(uint256 userId) public view virtual returns (ebytes64) { + if (!registered[userId]) revert DiplomaNotRegistered(); + return diplomaRecords[userId].university; + } + + /** + * @dev Retrieves encrypted degree type for a user + * @param userId ID of the user to get degree for + * @return euint8 Encrypted degree type + */ + function getMyDegree(uint256 userId) public view virtual returns (euint16) { + if (!registered[userId]) revert DiplomaNotRegistered(); + return diplomaRecords[userId].degree; + } + + /** + * @dev Retrieves encrypted grade for a user + * @param userId ID of the user to get grade for + * @return euint8 Encrypted grade + */ + function getMyGrade(uint256 userId) public view virtual returns (ebytes64) { + if (!registered[userId]) revert DiplomaNotRegistered(); + return diplomaRecords[userId].grade; + } + + /** + * @dev Checks if a diploma is registered for a user + * @param userId ID of the user to check + * @return bool indicating if diploma exists + */ + function hasDiploma(uint256 userId) public view virtual returns (bool) { + return registered[userId]; + } + + /** + * @dev Generates a claim for a diploma + * @param claimAddress Address of the claim contract + * @param claimFn Function signature to call on claim contract + */ + function generateClaim(address claimAddress, string memory claimFn) public { + /// @dev Only the msg.sender that is registered under the user ID can make the claim + uint256 userId = idMapping.getId(msg.sender); + + /// @dev Grant temporary access for graduate's data to be used in claim generation + TFHE.allowTransient(diplomaRecords[userId].degree, claimAddress); + + /// @dev Ensure the sender can access this graduate's data + if (!TFHE.isSenderAllowed(diplomaRecords[userId].degree)) revert AccessNotPermitted(); + + /// @dev Attempt the external call and capture the result + (bool success, bytes memory data) = claimAddress.call(abi.encodeWithSignature(claimFn, userId)); + if (!success) revert ClaimGenerationFailed(data); + + emit ClaimGenerated(msg.sender, claimAddress, claimFn); /// @dev Emit event for claim generation + } +} diff --git a/hardhat/contracts/decIdentity/EmployerClaim.sol b/hardhat/contracts/decIdentity/EmployerClaim.sol new file mode 100644 index 0000000..56d41fd --- /dev/null +++ b/hardhat/contracts/decIdentity/EmployerClaim.sol @@ -0,0 +1,207 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import "fhevm/lib/TFHE.sol"; +import "./PassportID.sol"; +import "./Diploma.sol"; +import "@openzeppelin/contracts/access/Ownable2Step.sol"; +import "fhevm/config/ZamaFHEVMConfig.sol"; + +/** + * @title EmployerClaim + * @author ZAMA + * @dev Contract for managing encrypted claims about users' age and education credentials + * @notice Allows generation and verification of encrypted claims for employment verification + */ +contract EmployerClaim is SepoliaZamaFHEVMConfig, Ownable2Step { + /// @dev Age threshold timestamp for adult verification (Jan 1, 2006 - 18 years on Jan 1, 2024) + uint64 private constant AGE_THRESHOLD_TIMESTAMP = 1136070000; + /// @dev Required degree level for education verification (Computer Science (B.Sc)) + uint16 private constant REQUIRED_DEGREE_LEVEL = 3; + /// @dev Constant representing an invalid claim ID + uint256 private constant INVALID_CLAIM = 0; + euint64 private _AGE_THRESHOLD; + euint16 private _REQUIRED_DEGREE; + + /// @dev Error thrown when an invalid claim ID is provided + error InvalidClaimId(); + /// @dev Error thrown when an invalid contract address is provided + error InvalidContractAddress(); + /// @dev Error thrown when caller is not authorized + error NotAuthorized(); + + /// @dev Counter for tracking the latest claim ID + uint64 public lastClaimId = 0; + /// @dev Mapping of claim IDs to encrypted boolean results for adult claims + mapping(uint64 => ebool) private adultClaims; + /// @dev Mapping of claim IDs to encrypted boolean results for degree claims + mapping(uint64 => ebool) private degreeClaims; + /// @dev Mapping of user IDs to encrypted boolean results for verified claims + mapping(uint256 => ebool) private verifiedClaims; + + /// @dev Emitted when an adult claim is generated + /// @param claimId The ID of the generated claim + /// @param userId The ID of the user the claim is for + event AdultClaimGenerated(uint64 claimId, uint256 userId); + /// @dev Emitted when a degree claim is generated + /// @param claimId The ID of the generated claim + /// @param userId The ID of the user the claim is for + event DegreeClaimGenerated(uint64 claimId, uint256 userId); + + /// @dev Instance of IdMapping contract for user ID management + IdMapping private idMapping; + /// @dev Instance of PassportID contract for identity verification + PassportID private passportContract; + /// @dev Instance of Diploma contract for education verification + Diploma private diplomaContract; + + /** + * @dev Constructor to initialize the contract with required contract addresses + * @param _idMappingAddress Address of the IdMapping contract + * @param _passportAddress Address of the PassportID contract + * @param _diplomaAddress Address of the Diploma contract + * @custom:throws InvalidContractAddress if any address is zero + */ + constructor(address _idMappingAddress, address _passportAddress, address _diplomaAddress) Ownable(msg.sender) { + if (_idMappingAddress == address(0) || _passportAddress == address(0) || _diplomaAddress == address(0)) + revert InvalidContractAddress(); + + idMapping = IdMapping(_idMappingAddress); + passportContract = PassportID(_passportAddress); + diplomaContract = Diploma(_diplomaAddress); + + /// Set age threshold to 18 years (in Unix timestamp) + _AGE_THRESHOLD = TFHE.asEuint64(AGE_THRESHOLD_TIMESTAMP); + + /// Use constant for required degree + _REQUIRED_DEGREE = TFHE.asEuint16(REQUIRED_DEGREE_LEVEL); + + TFHE.allowThis(_AGE_THRESHOLD); + TFHE.allowThis(_REQUIRED_DEGREE); + } + + /** + * @dev Generates an encrypted claim verifying if a user is above 18 years old + * @param userId The ID of the user to generate the claim for + * @return The ID of the generated claim + * @custom:throws NotAuthorized if caller is not the passport contract + * @custom:emits AdultClaimGenerated when claim is generated + */ + function generateAdultClaim(uint256 userId) public returns (uint64) { + if (msg.sender != address(passportContract)) revert NotAuthorized(); + + /// Retrieve the address associated with the user ID + address addressToBeAllowed = idMapping.getAddr(userId); + + /// Retrieve the user's encrypted birthdate from the PassportID contract + euint64 birthdate = passportContract.getBirthdate(userId); + + lastClaimId++; + + /// Check if birthdate indicates user is over 18 + ebool isAdult = TFHE.le(birthdate, _AGE_THRESHOLD); + + /// Store the result of the claim + adultClaims[lastClaimId] = isAdult; + + /// Grant access to the claim to both the contract and user for verification purposes + TFHE.allowThis(isAdult); + TFHE.allow(isAdult, addressToBeAllowed); + + /// Emit an event for the generated claim + emit AdultClaimGenerated(lastClaimId, userId); + + return lastClaimId; + } + + /** + * @dev Retrieves the result of an adult claim + * @param claimId The ID of the claim to retrieve + * @return The encrypted boolean result of the claim + * @custom:throws InvalidClaimId if claim ID is invalid + */ + function getAdultClaim(uint64 claimId) public view returns (ebool) { + if (claimId == 0 || claimId > lastClaimId) revert InvalidClaimId(); + return adultClaims[claimId]; + } + + /** + * @dev Generates an encrypted claim verifying if a user has required degree credentials + * @param userId The ID of the user to generate the claim for + * @return The ID of the generated claim + * @custom:throws NotAuthorized if caller is not the diploma contract + * @custom:emits DegreeClaimGenerated when claim is generated + */ + function generateDegreeClaim(uint256 userId) public returns (uint64) { + if (msg.sender != address(diplomaContract)) revert NotAuthorized(); + + /// Retrieve the address associated with the user ID + address addressToBeAllowed = idMapping.getAddr(userId); + + /// Get the diploma data from the Diploma contract + euint16 userUniversity = diplomaContract.getMyDegree(userId); + + lastClaimId++; + + /// Check if university and degree match requirements + ebool degreeMatch = TFHE.eq(userUniversity, _REQUIRED_DEGREE); + + /// Store the result of the claim + degreeClaims[lastClaimId] = degreeMatch; + + /// Grant access to the claim + TFHE.allowThis(degreeMatch); + TFHE.allow(degreeMatch, addressToBeAllowed); + + /// Emit an event for the generated claim + emit DegreeClaimGenerated(lastClaimId, userId); + + return lastClaimId; + } + + /** + * @dev Retrieves the result of a degree claim + * @param claimId The ID of the claim to retrieve + * @return The encrypted boolean result of the claim + * @custom:throws InvalidClaimId if claim ID is invalid + */ + function getDegreeClaim(uint64 claimId) public view returns (ebool) { + if (claimId == 0 || claimId > lastClaimId) revert InvalidClaimId(); + return degreeClaims[claimId]; + } + + /** + * @dev Verifies both adult and degree claims for a user + * @param userId The ID of the user to verify claims for + * @param adultClaim The ID of the adult claim to verify + * @param degreeClaim The ID of the degree claim to verify + * @custom:throws InvalidClaimId if either claim ID is invalid + * @notice This function combines adult and degree claims into a single verification + */ + function verifyClaims(uint256 userId, uint64 adultClaim, uint64 degreeClaim) public { + if (adultClaim == INVALID_CLAIM || adultClaim > lastClaimId) revert InvalidClaimId(); + if (degreeClaim == INVALID_CLAIM || degreeClaim > lastClaimId) revert InvalidClaimId(); + + ebool isAdult = adultClaims[adultClaim]; + ebool degreeMatch = degreeClaims[degreeClaim]; + + ebool verify = TFHE.and(isAdult, degreeMatch); + + /// Store the verification result under the userId mapping + verifiedClaims[userId] = verify; + + /// Grant access to the claim + TFHE.allowThis(verify); + TFHE.allow(verify, owner()); + } + + /** + * @dev Retrieves the result of a verified claim for a user + * @param userId The ID of the user to get the verified claim for + * @return The encrypted boolean result of the verified claim + * @notice Returns the combined verification status of adult and degree claims + */ + function getVerifyClaim(uint256 userId) public view returns (ebool) { + return verifiedClaims[userId]; + } +} diff --git a/hardhat/contracts/decIdentity/IdMapping.sol b/hardhat/contracts/decIdentity/IdMapping.sol new file mode 100644 index 0000000..4d28ea4 --- /dev/null +++ b/hardhat/contracts/decIdentity/IdMapping.sol @@ -0,0 +1,114 @@ +/// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "@openzeppelin/contracts/access/Ownable2Step.sol"; +import "fhevm/config/ZamaFHEVMConfig.sol"; + +/** + * @title IdMapping + * @author ZAMA + * @notice Manages unique ID mappings between addresses and sequential IDs + * @dev Inherits from Ownable2Step for secure ownership transfer + */ +contract IdMapping is SepoliaZamaFHEVMConfig, Ownable2Step { + /// Custom errors + /// @notice Thrown when attempting to generate an ID for an address that already has one + error IdAlreadyGenerated(); + /// @notice Thrown when attempting to use the zero address + error InvalidAddress(); + /// @notice Thrown when the maximum ID value has been reached + error IdOverflow(); + /// @notice Thrown when trying to look up an ID for an address that hasn't generated one + error NoIdGenerated(); + /// @notice Thrown when attempting to use an ID that doesn't exist + error InvalidId(); + /// @notice Thrown when no address is found for a given ID + error NoAddressFound(); + + /// @notice Maps user addresses to their unique IDs + mapping(address => uint256) public addressToId; + /// @dev Maps unique IDs back to user addresses + mapping(uint256 => address) private idToAddress; + /// @dev Counter for assigning sequential IDs, starts at 1 + uint256 private nextId = 1; + + /** + * @notice Emitted when a new ID is generated for a user + * @param user The address of the user receiving the ID + * @param id The unique ID assigned to the user + */ + event IdGenerated(address indexed user, uint256 indexed id); + + /** + * @notice Initializes the contract with the deployer as owner + * @dev Sets initial ID counter to 1 + */ + constructor() Ownable(msg.sender) { + nextId = 1; + } + + /** + * @notice Generates a unique ID for the calling address + * @dev Each address can only generate one ID. IDs are assigned sequentially starting from 1 + * @return uint256 The newly generated ID + * @custom:throws IdAlreadyGenerated if caller already has an ID + * @custom:throws InvalidAddress if caller is zero address + * @custom:throws IdOverflow if maximum ID value is reached + */ + function generateId() public returns (uint256) { + if (addressToId[msg.sender] != 0) revert IdAlreadyGenerated(); + if (msg.sender == address(0)) revert InvalidAddress(); + + uint256 newId = nextId; + + addressToId[msg.sender] = newId; + idToAddress[newId] = msg.sender; + nextId++; + + emit IdGenerated(msg.sender, newId); + return newId; + } + + /** + * @notice Looks up the ID associated with a given address + * @dev Reverts if address has no ID or is zero address + * @param _addr The address to lookup + * @return uint256 The ID associated with the address + * @custom:throws InvalidAddress if provided address is zero address + * @custom:throws NoIdGenerated if address has no ID assigned + */ + function getId(address _addr) public view returns (uint256) { + if (_addr == address(0)) revert InvalidAddress(); + if (addressToId[_addr] == 0) revert NoIdGenerated(); + return addressToId[_addr]; + } + + /** + * @notice Looks up the address associated with a given ID + * @dev Reverts if ID is invalid or has no associated address + * @param _id The ID to lookup + * @return address The address associated with the ID + * @custom:throws InvalidId if ID is 0 or greater than the last assigned ID + * @custom:throws NoAddressFound if no address is associated with the ID + */ + function getAddr(uint256 _id) public view returns (address) { + if (_id <= 0 || _id >= nextId) revert InvalidId(); + address addr = idToAddress[_id]; + if (addr == address(0)) revert NoAddressFound(); + return addr; + } + + /** + * @notice Removes an address's ID mapping + * @dev Only callable by contract owner. Removes both address->ID and ID->address mappings + * @param _addr The address whose ID mapping should be reset + * @custom:throws NoIdGenerated if address has no ID assigned + */ + function resetIdForAddress(address _addr) external onlyOwner { + uint256 id = addressToId[_addr]; + if (id == 0) revert NoIdGenerated(); + + delete addressToId[_addr]; + delete idToAddress[id]; + } +} diff --git a/hardhat/contracts/decIdentity/PassportID.sol b/hardhat/contracts/decIdentity/PassportID.sol new file mode 100644 index 0000000..a717e85 --- /dev/null +++ b/hardhat/contracts/decIdentity/PassportID.sol @@ -0,0 +1,243 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import "fhevm/lib/TFHE.sol"; +import "./IdMapping.sol"; +import "@openzeppelin/contracts/access/AccessControl.sol"; +import "fhevm/config/ZamaFHEVMConfig.sol"; + +/** + * @title PassportID + * @author ZAMA + * @notice Manages encrypted passport identity data and verification claims + * @dev Implements role-based access control for registrars and admins to manage identity registration + */ +contract PassportID is SepoliaZamaFHEVMConfig, AccessControl { + /// @dev Constants + bytes32 public constant REGISTRAR_ROLE = keccak256("REGISTRAR_ROLE"); + bytes32 public constant OWNER_ROLE = keccak256("OWNER_ROLE"); + + /// @dev Custom errors + /// @notice Thrown when attempting to register an identity for a user who already has one + error AlreadyRegistered(); + /// @notice Thrown when attempting to access identity data for a user who doesn't have one registered + error IdentityNotRegistered(); + /// @notice Thrown when sender doesn't have permission to access the encrypted data + error AccessNotPermitted(); + /// @notice Thrown when claim generation fails, includes failure data + /// @param data The error data returned from the failed claim generation + error ClaimGenerationFailed(bytes data); + error InvalidField(); + + /** + * @dev Structure to hold encrypted identity data + * @param id Encrypted unique identifier for the identity record + * @param biodata Encrypted biometric data like fingerprints or facial data + * @param firstname Encrypted legal first name from passport + * @param lastname Encrypted legal last name from passport + * @param birthdate Encrypted date of birth in unix timestamp format + */ + struct Identity { + euint64 id; /// @dev Encrypted unique ID + ebytes64 biodata; /// @dev Encrypted biodata (e.g., biometric data or hashed identity data) + ebytes64 firstname; /// @dev Encrypted first name + ebytes64 lastname; /// @dev Encrypted last name + euint64 birthdate; /// @dev Encrypted birthdate for age verification + } + + /// @dev Instance of IdMapping contract + IdMapping private idMapping; + + /// @dev Mapping to store identities by user ID + mapping(uint256 => Identity) private citizenIdentities; + /// @dev Mapping to track registered identities + mapping(uint256 => bool) public registered; + + /// @dev Event emitted when an identity is registered + event IdentityRegistered(address indexed user); + + /** + * @notice Initializes the passport identity management system + * @dev Sets up FHEVM config and grants admin/registrar roles to deployer + * @param _idMappingAddress Address of the IdMapping contract for user ID management + */ + constructor(address _idMappingAddress) { + idMapping = IdMapping(_idMappingAddress); + _grantRole(OWNER_ROLE, msg.sender); /// @dev Admin role for contract owner + _grantRole(REGISTRAR_ROLE, msg.sender); /// @dev Registrar role for contract owner + } + + /** + * @notice Grants registrar privileges to a new address + * @dev Only callable by admin role + * @param registrar Address to be granted registrar permissions + */ + function addRegistrar(address registrar) external onlyRole(OWNER_ROLE) { + _grantRole(REGISTRAR_ROLE, registrar); + } + + /** + * @notice Revokes registrar privileges from an address + * @dev Only callable by admin role + * @param registrar Address to have registrar permissions revoked + */ + function removeRegistrar(address registrar) external onlyRole(OWNER_ROLE) { + _revokeRole(REGISTRAR_ROLE, registrar); + } + + /** + * @notice Creates a new encrypted identity record + * @dev Only admin role can register new identities. All data is stored in encrypted form + * @param userId Unique identifier for the user from IdMapping contract + * @param biodata Encrypted biometric/identity data with proof + * @param firstname Encrypted first name with proof + * @param lastname Encrypted last name with proof + * @param birthdate Encrypted birthdate with proof + * @param inputProof Zero-knowledge proof validating the encrypted inputs + * @return bool True if registration was successful + * @custom:throws AlreadyRegistered if userId already has an identity registered + */ + function registerIdentity( + uint256 userId, + einput biodata, + einput firstname, + einput lastname, + einput birthdate, + bytes calldata inputProof + ) public virtual onlyRole(REGISTRAR_ROLE) returns (bool) { + if (registered[userId]) revert AlreadyRegistered(); + + /// @dev Generate a new encrypted unique ID + euint64 newId = TFHE.randEuint64(); + + /// @dev Store the encrypted identity data + citizenIdentities[userId] = Identity({ + id: newId, + biodata: TFHE.asEbytes64(biodata, inputProof), + firstname: TFHE.asEbytes64(firstname, inputProof), + lastname: TFHE.asEbytes64(lastname, inputProof), + birthdate: TFHE.asEuint64(birthdate, inputProof) + }); + + registered[userId] = true; /// @dev Mark the identity as registered + + /// @dev Get the address associated with the user ID + address addressToBeAllowed = idMapping.getAddr(userId); + + /// @dev Allow the user to access their own data + TFHE.allow(citizenIdentities[userId].id, addressToBeAllowed); + TFHE.allow(citizenIdentities[userId].biodata, addressToBeAllowed); + TFHE.allow(citizenIdentities[userId].firstname, addressToBeAllowed); + TFHE.allow(citizenIdentities[userId].lastname, addressToBeAllowed); + TFHE.allow(citizenIdentities[userId].birthdate, addressToBeAllowed); + + /// @dev Allow the contract to access the data + TFHE.allowThis(citizenIdentities[userId].id); + TFHE.allowThis(citizenIdentities[userId].biodata); + TFHE.allowThis(citizenIdentities[userId].firstname); + TFHE.allowThis(citizenIdentities[userId].lastname); + TFHE.allowThis(citizenIdentities[userId].birthdate); + + emit IdentityRegistered(addressToBeAllowed); /// @dev Emit event for identity registration + + return true; + } + + /** + * @notice Retrieves the complete encrypted identity record for a user + * @dev Returns all encrypted identity fields as a tuple + * @param userId ID of the user whose identity to retrieve + * @return Tuple containing (id, biodata, firstname, lastname, birthdate) + * @custom:throws IdentityNotRegistered if no identity exists for userId + */ + function getIdentity(uint256 userId) public view virtual returns (euint64, ebytes64, ebytes64, ebytes64, euint64) { + if (!registered[userId]) revert IdentityNotRegistered(); + return ( + citizenIdentities[userId].id, + citizenIdentities[userId].biodata, + citizenIdentities[userId].firstname, + citizenIdentities[userId].lastname, + citizenIdentities[userId].birthdate + ); + } + + /** + * @notice Retrieves only the encrypted birthdate for a user + * @dev Useful for age verification claims + * @param userId ID of the user whose birthdate to retrieve + * @return Encrypted birthdate as euint64 + * @custom:throws IdentityNotRegistered if no identity exists for userId + */ + function getBirthdate(uint256 userId) public view virtual returns (euint64) { + if (!registered[userId]) revert IdentityNotRegistered(); + return citizenIdentities[userId].birthdate; + } + + /** + * @notice Retrieves only the encrypted first name for a user + * @dev Useful for identity verification claims + * @param userId ID of the user whose first name to retrieve + * @return Encrypted first name as euint8 + * @custom:throws IdentityNotRegistered if no identity exists for userId + */ + function getMyIdentityFirstname(uint256 userId) public view virtual returns (ebytes64) { + if (!registered[userId]) revert IdentityNotRegistered(); + return citizenIdentities[userId].firstname; + } + + /** + * @notice Generates a verification claim using the user's identity data + * @dev Temporarily grants claim contract access to required encrypted data + * @param claimAddress Contract address that will process the claim + * @param claimFn Function signature in the claim contract to call + * @custom:throws AccessNotPermitted if sender lacks permission to access data + * @custom:throws ClaimGenerationFailed if external claim call fails + */ + function generateClaim(address claimAddress, string memory claimFn) public { + /// @dev Only the msg.sender that is registered under the user ID can make the claim + uint256 userId = idMapping.getId(msg.sender); + + /// @dev Grant temporary access for citizen's birthdate to be used in claim generation + TFHE.allowTransient(citizenIdentities[userId].birthdate, claimAddress); + + /// @dev Ensure the sender can access this citizen's birthdate + if (!TFHE.isSenderAllowed(citizenIdentities[userId].birthdate)) revert AccessNotPermitted(); + + /// @dev Attempt the external call and capture the result + (bool success, bytes memory data) = claimAddress.call(abi.encodeWithSignature(claimFn, userId)); + if (!success) revert ClaimGenerationFailed(data); + } + + /** + * @notice Generates a verification claim using the user's identity data + * @dev Temporarily grants claim contract access to required encrypted data + * @param claimAddress Contract address that will process the claim + * @param claimFn Function signature in the claim contract to call + * @custom:throws AccessNotPermitted if sender lacks permission to access data + * @custom:throws ClaimGenerationFailed if external claim call fails + */ + function generateClaim(address claimAddress, string memory claimFn, string[] memory fields) public { + /// @dev Only the msg.sender that is registered under the user ID can make the claim + uint256 userId = idMapping.getId(msg.sender); + + /// @dev Grant temporary access for each requested field + for (uint i = 0; i < fields.length; i++) { + if (bytes(fields[i]).length == 0) revert InvalidField(); + + if (keccak256(bytes(fields[i])) == keccak256(bytes("id"))) { + TFHE.allowTransient(citizenIdentities[userId].id, claimAddress); + /// @dev Ensure the sender can access this citizen's university + if (!TFHE.isSenderAllowed(citizenIdentities[userId].id)) revert AccessNotPermitted(); + } else if (keccak256(bytes(fields[i])) == keccak256(bytes("birthdate"))) { + TFHE.allowTransient(citizenIdentities[userId].birthdate, claimAddress); + if (!TFHE.isSenderAllowed(citizenIdentities[userId].birthdate)) revert AccessNotPermitted(); + } else { + revert InvalidField(); + } + } + + /// @dev Attempt the external call and capture the result + (bool success, bytes memory data) = claimAddress.call(abi.encodeWithSignature(claimFn, userId)); + if (!success) revert ClaimGenerationFailed(data); + } +} diff --git a/hardhat/deploy/deploy.ts b/hardhat/deploy/deploy.ts new file mode 100644 index 0000000..017d33d --- /dev/null +++ b/hardhat/deploy/deploy.ts @@ -0,0 +1,32 @@ +import { DeployFunction } from "hardhat-deploy/types"; +import { HardhatRuntimeEnvironment } from "hardhat/types"; + +const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { + const { deployer } = await hre.getNamedAccounts(); + const { deploy, getOrNull } = hre.deployments; + + // Check if contract was previously deployed + const existingDeployment = await getOrNull("MyConfidentialERC20"); + const isNewDeployment = !existingDeployment; + + const deployed = await deploy("MyConfidentialERC20", { + from: deployer, + args: ["Naraggara", "NARA"], + log: true, + }); + + console.log(`MyConfidentialERC20 contract: `, deployed.address); + if (isNewDeployment) { + const signers = await hre.ethers.getSigners(); + const alice = signers[0]; + const mintAmount = 10_000n; + const tokenFactory = await hre.ethers.getContractFactory("MyConfidentialERC20"); + const token = tokenFactory.attach(deployed.address); + const mintTx = await token.mint(alice, mintAmount); + await mintTx.wait(); + console.log(`Alice minted ${mintAmount} tokens to herself`); + } +}; +export default func; +func.id = "deploy_confidentialERC20"; // id required to prevent reexecution +func.tags = ["MyConfidentialERC20"]; diff --git a/hardhat/eslint.config.mjs b/hardhat/eslint.config.mjs new file mode 100644 index 0000000..9a73964 --- /dev/null +++ b/hardhat/eslint.config.mjs @@ -0,0 +1,17 @@ +import eslint from "@eslint/js"; +import globals from "globals"; +import tseslint from "typescript-eslint"; + +export default [ + { + languageOptions: { + globals: globals.node, + }, + linterOptions: { + reportUnusedDisableDirectives: "off", + }, + ignores: [".abi/", ".artifacts/", ".cache/", ".coverage/", ".res/", ".types/"], + }, + eslint.configs.recommended, + ...tseslint.configs.recommended, +]; diff --git a/hardhat/hardhat.config.ts b/hardhat/hardhat.config.ts new file mode 100644 index 0000000..e077eb3 --- /dev/null +++ b/hardhat/hardhat.config.ts @@ -0,0 +1,154 @@ +import "@nomicfoundation/hardhat-toolbox"; +import "@openzeppelin/hardhat-upgrades"; +import { spawn } from "child_process"; +import dotenv from "dotenv"; +import "hardhat-deploy"; +import "hardhat-ignore-warnings"; +import { HardhatUserConfig, extendProvider } from "hardhat/config"; +import { task } from "hardhat/config"; +import type { NetworkUserConfig } from "hardhat/types"; + +import CustomProvider from "./CustomProvider"; +// Adjust the import path as needed +import "./tasks/accounts"; +import "./tasks/etherscanVerify"; +import "./tasks/mintMyConfidentialERC20"; +import { setCodeMocked } from "./test/mockedSetup"; + +extendProvider(async (provider) => { + const newProvider = new CustomProvider(provider); + return newProvider; +}); + +dotenv.config(); + +// Ensure that we have all the environment variables we need. +const mnemonic: string = process.env.MNEMONIC!; + +const chainIds = { + zama: 8009, + local: 9000, + localCoprocessor: 12345, + sepolia: 11155111, +}; + +function getChainConfig(chain: keyof typeof chainIds): NetworkUserConfig { + let jsonRpcUrl: string; + switch (chain) { + case "local": + jsonRpcUrl = "http://localhost:8545"; + break; + case "localCoprocessor": + jsonRpcUrl = "http://localhost:8745"; + break; + case "zama": + jsonRpcUrl = "https://devnet.zama.ai"; + break; + case "sepolia": + jsonRpcUrl = process.env.SEPOLIA_RPC_URL!; + } + return { + accounts: { + count: 10, + mnemonic, + path: "m/44'/60'/0'/0", + }, + chainId: chainIds[chain], + url: jsonRpcUrl, + }; +} + +task("coverage").setAction(async (taskArgs, hre, runSuper) => { + hre.config.networks.hardhat.allowUnlimitedContractSize = true; + hre.config.networks.hardhat.blockGasLimit = 1099511627775; + + await runSuper(taskArgs); +}); + +task("test", async (_taskArgs, hre, runSuper) => { + // Run modified test task + if (hre.network.name === "hardhat") { + await setCodeMocked(hre); + } + await runSuper(); +}); + +task("node", async (_taskArgs, hre, runSuper) => { + await setCodeMocked(hre); + const server = spawn("ts-node", ["--transpile-only", "mockedServices/server.ts"], { + stdio: "inherit", + }); + + process.on("SIGINT", () => { + server.kill(); + process.exit(0); + }); + await runSuper(); +}); + +const config: HardhatUserConfig = { + defaultNetwork: "hardhat", + namedAccounts: { + deployer: 0, + }, + mocha: { + timeout: 500000, + }, + gasReporter: { + currency: "USD", + enabled: process.env.REPORT_GAS ? true : false, + excludeContracts: [], + src: "./contracts", + }, + networks: { + hardhat: { + accounts: { + count: 10, + mnemonic, + path: "m/44'/60'/0'/0", + }, + }, + sepolia: getChainConfig("sepolia"), + zama: getChainConfig("zama"), + localDev: getChainConfig("local"), + local: getChainConfig("local"), + localCoprocessor: getChainConfig("localCoprocessor"), + }, + paths: { + artifacts: "./artifacts", + cache: "./cache", + sources: "./contracts", + tests: "./test", + }, + solidity: { + version: "0.8.24", + settings: { + metadata: { + // Not including the metadata hash + // https://github.com/paulrberg/hardhat-template/issues/31 + bytecodeHash: "none", + }, + // Disable the optimizer when debugging + // https://hardhat.org/hardhat-network/#solidity-optimizer-support + optimizer: { + enabled: true, + runs: 800, + }, + evmVersion: "cancun", + }, + }, + etherscan: { + apiKey: process.env.ETHERSCAN_API_KEY!, + }, + warnings: { + "*": { + "transient-storage": false, + }, + }, + typechain: { + outDir: "types", + target: "ethers-v6", + }, +}; + +export default config; diff --git a/hardhat/mockedServices/asyncDecrypt.ts b/hardhat/mockedServices/asyncDecrypt.ts new file mode 100644 index 0000000..a94d327 --- /dev/null +++ b/hardhat/mockedServices/asyncDecrypt.ts @@ -0,0 +1,157 @@ +import { Wallet, ZeroAddress } from "ethers"; +import { ethers } from "ethers"; +import aclArtifact from "fhevm-core-contracts/artifacts/contracts/ACL.sol/ACL.json"; +import gatewayArtifact from "fhevm-core-contracts/artifacts/gateway/GatewayContract.sol/GatewayContract.json"; + +import { ACL_ADDRESS, GATEWAYCONTRACT_ADDRESS, KMSVERIFIER_ADDRESS, PRIVATE_KEY_KMS_SIGNER } from "../test/constants"; +import { awaitCoprocessor, getClearText } from "./coprocessorUtils"; + +const aclAdd = ACL_ADDRESS; + +const CiphertextType = { + 0: "bool", + 1: "uint8", // corresponding to euint4 + 2: "uint8", // corresponding to euint8 + 3: "uint16", + 4: "uint32", + 5: "uint64", + 6: "uint128", + 7: "address", + 8: "uint256", + 9: "bytes", + 10: "bytes", + 11: "bytes", +}; + +const currentTime = (): string => { + const now = new Date(); + return now.toLocaleTimeString("en-US", { hour12: true, hour: "numeric", minute: "numeric", second: "numeric" }); +}; + +const argEvents = + "(uint256 indexed requestID, uint256[] cts, address contractCaller, bytes4 callbackSelector, uint256 msgValue, uint256 maxTimestamp, bool passSignaturesToCaller)"; +const ifaceEventDecryption = new ethers.Interface(["event EventDecryption" + argEvents]); + +const provider = new ethers.WebSocketProvider("ws://127.0.0.1:8545"); +const acl = new ethers.Contract(ACL_ADDRESS, aclArtifact.abi, provider); +const gateway = new ethers.Contract(GATEWAYCONTRACT_ADDRESS, gatewayArtifact.abi, provider); + +export const initGateway = async (): Promise => { + gateway.on("EventDecryption", async (requestID, cts) => { + console.log(`${await currentTime()} - Requested decrypt (requestID ${requestID}) for handles ${cts}`); + await fulfillRequest(requestID, cts); + }); +}; + +const allTrue = (arr: boolean[], fn = Boolean) => arr.every(fn); + +const fulfillRequest = async (requestID: bigint, handles: bigint[]) => { + await awaitCoprocessor(); + + const typesList = handles.map((handle) => parseInt(handle.toString(16).slice(-4, -2), 16)); + + const isAllowedForDec = await Promise.all(handles.map(async (handle) => acl.isAllowedForDecryption(handle))); + if (!allTrue(isAllowedForDec)) { + throw new Error("Some handle is not authorized for decryption"); + } + + const types = typesList.map((num) => CiphertextType[num]); + const values = await Promise.all(handles.map(async (handle) => BigInt(await getClearText(handle)))); + const valuesFormatted = values.map((value, index) => + types[index] === "address" ? "0x" + value.toString(16).padStart(40, "0") : value, + ); + const valuesFormatted2 = valuesFormatted.map((value, index) => + typesList[index] === 9 ? "0x" + value.toString(16).padStart(128, "0") : value, + ); + const valuesFormatted3 = valuesFormatted2.map((value, index) => + typesList[index] === 10 ? "0x" + value.toString(16).padStart(256, "0") : value, + ); + const valuesFormatted4 = valuesFormatted3.map((value, index) => + typesList[index] === 11 ? "0x" + value.toString(16).padStart(512, "0") : value, + ); + + const abiCoder = new ethers.AbiCoder(); + let encodedData; + let calldata; + + encodedData = abiCoder.encode(["uint256", ...types], [31, ...valuesFormatted4]); // 31 is just a dummy uint256 requestID to get correct abi encoding for the remaining arguments (i.e everything except the requestID) + calldata = "0x" + encodedData.slice(66); // we just pop the dummy requestID to get the correct value to pass for `decryptedCts` + + const numSigners = 1; // for the moment mocked mode only uses 1 signer + const decryptResultsEIP712signatures = await computeDecryptSignatures(handles, calldata, numSigners); + await provider.send("hardhat_impersonateAccount", [ZeroAddress]); + const impersonatedSigner = new ethers.JsonRpcSigner(provider, ZeroAddress); + const tx = await gateway + .connect(impersonatedSigner) + .fulfillRequest(requestID, calldata, decryptResultsEIP712signatures); + await tx.wait(); + await provider.send("hardhat_stopImpersonatingAccount", [ZeroAddress]); + + const blockNumber = await provider.send("eth_blockNumber", []); + console.log( + `Gateway sent decryption result in callback tx succesfully for requestID ${requestID} on block no ${blockNumber}`, + ); +}; + +async function computeDecryptSignatures( + handlesList: bigint[], + decryptedResult: string, + numSigners: number, +): Promise { + const signatures: string[] = []; + + for (let idx = 0; idx < numSigners; idx++) { + const privKeySigner = PRIVATE_KEY_KMS_SIGNER; + if (privKeySigner) { + const kmsSigner = new ethers.Wallet(privKeySigner).connect(provider); + const signature = await kmsSign(handlesList, decryptedResult, kmsSigner); + signatures.push(signature); + } else { + throw new Error(`Private key for signer ${idx} not found in environment variables`); + } + } + return signatures; +} + +async function kmsSign(handlesList: bigint[], decryptedResult: string, kmsSigner: Wallet) { + const kmsAdd = KMSVERIFIER_ADDRESS; + const chainId = (await provider.getNetwork()).chainId; + + const domain = { + name: "KMSVerifier", + version: "1", + chainId: chainId, + verifyingContract: kmsAdd, + }; + + const types = { + DecryptionResult: [ + { + name: "aclAddress", + type: "address", + }, + { + name: "handlesList", + type: "uint256[]", + }, + { + name: "decryptedResult", + type: "bytes", + }, + ], + }; + const message = { + aclAddress: aclAdd, + handlesList: handlesList, + decryptedResult: decryptedResult, + }; + + const signature = await kmsSigner.signTypedData(domain, types, message); + const sigRSV = ethers.Signature.from(signature); + const v = 27 + sigRSV.yParity; + const r = sigRSV.r; + const s = sigRSV.s; + + const result = r + s.substring(2) + v.toString(16); + return result; +} diff --git a/hardhat/mockedServices/coprocessorUtils.ts b/hardhat/mockedServices/coprocessorUtils.ts new file mode 100644 index 0000000..c7cbbbd --- /dev/null +++ b/hardhat/mockedServices/coprocessorUtils.ts @@ -0,0 +1,583 @@ +import { JsonRpcProvider } from "ethers"; +import { ethers } from "ethers"; +import { log2 } from "extra-bigint"; +import { Database } from "sqlite3"; + +import { TFHEEXECUTOR_ADDRESS } from "../test/constants"; + +const provider = new JsonRpcProvider("http://127.0.0.1:8545"); + +const executorAddress = TFHEEXECUTOR_ADDRESS; + +let firstBlockListening = 0; +let counterRand = 0; + +//const db = new Database("./sql.db"); // on-disk db for debugging +const db = new Database(":memory:"); + +export function insertSQL(handle: string, clearText: bigint, replace: boolean = false) { + if (replace) { + // this is useful if using snapshots while sampling different random numbers on each revert + db.run("INSERT OR REPLACE INTO ciphertexts (handle, clearText) VALUES (?, ?)", [handle, clearText.toString()]); + } else { + db.run("INSERT OR IGNORE INTO ciphertexts (handle, clearText) VALUES (?, ?)", [handle, clearText.toString()]); + } +} + +// Decrypt any handle, bypassing ACL +// WARNING : only for testing or internal use +export const getClearText = async (handle: bigint): Promise => { + const handleStr = "0x" + handle.toString(16).padStart(64, "0"); + + return new Promise((resolve, reject) => { + let attempts = 0; + const maxRetries = 100; + + function executeQuery() { + db.get("SELECT clearText FROM ciphertexts WHERE handle = ?", [handleStr], (err, row) => { + if (err) { + reject(new Error(`Error querying database: ${err.message}`)); + } else if (row) { + resolve(row.clearText); + } else if (attempts < maxRetries) { + attempts++; + executeQuery(); + } else { + reject(new Error("No record found after maximum retries")); + } + }); + } + + executeQuery(); + }); +}; + +db.serialize(() => db.run("CREATE TABLE IF NOT EXISTS ciphertexts (handle BINARY PRIMARY KEY,clearText TEXT)")); + +interface FHEVMEvent { + eventName: string; + args: object; +} + +const NumBits = { + 0: 1n, //ebool + 1: 4n, //euint4 + 2: 8n, //euint8 + 3: 16n, //euint16 + 4: 32n, //euint32 + 5: 64n, //euint64 + 6: 128n, //euint128 + 7: 160n, //eaddress + 8: 256n, //euint256 + 9: 512n, //ebytes64 + 10: 1024n, //ebytes128 + 11: 2048n, //ebytes256 +}; + +export function numberToEvenHexString(num: number) { + if (typeof num !== "number" || num < 0) { + throw new Error("Input should be a non-negative number."); + } + let hexString = num.toString(16); + if (hexString.length % 2 !== 0) { + hexString = "0" + hexString; + } + return hexString; +} + +function getRandomBigInt(numBits: number): bigint { + if (numBits <= 0) { + throw new Error("Number of bits must be greater than 0"); + } + const numBytes = Math.ceil(numBits / 8); + const randomBytes = new Uint8Array(numBytes); + crypto.getRandomValues(randomBytes); + let randomBigInt = BigInt(0); + for (let i = 0; i < numBytes; i++) { + randomBigInt = (randomBigInt << BigInt(8)) | BigInt(randomBytes[i]); + } + const mask = (BigInt(1) << BigInt(numBits)) - BigInt(1); + randomBigInt = randomBigInt & mask; + return randomBigInt; +} + +function bitwiseNotUintBits(value: bigint, numBits: number) { + if (typeof value !== "bigint") { + throw new TypeError("The input value must be a BigInt."); + } + if (typeof numBits !== "number" || numBits <= 0) { + throw new TypeError("The numBits parameter must be a positive integer."); + } + // Create the mask with numBits bits set to 1 + const BIT_MASK = (BigInt(1) << BigInt(numBits)) - BigInt(1); + return ~value & BIT_MASK; +} + +export const awaitCoprocessor = async (): Promise => { + await processAllPastTFHEExecutorEvents(); +}; + +const abi = [ + "event FheAdd(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheSub(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheMul(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheDiv(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheRem(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheBitAnd(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheBitOr(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheBitXor(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheShl(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheShr(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheRotl(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheRotr(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheEq(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheEqBytes(uint256 lhs, bytes rhs, bytes1 scalarByte, uint256 result)", + "event FheNe(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheNeBytes(uint256 lhs, bytes rhs, bytes1 scalarByte, uint256 result)", + "event FheGe(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheGt(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheLe(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheLt(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheMin(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheMax(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheNeg(uint256 ct, uint256 result)", + "event FheNot(uint256 ct, uint256 result)", + "event VerifyCiphertext(bytes32 inputHandle,address userAddress,bytes inputProof,bytes1 inputType,uint256 result)", + "event Cast(uint256 ct, bytes1 toType, uint256 result)", + "event TrivialEncrypt(uint256 pt, bytes1 toType, uint256 result)", + "event TrivialEncryptBytes(bytes pt, bytes1 toType, uint256 result)", + "event FheIfThenElse(uint256 control, uint256 ifTrue, uint256 ifFalse, uint256 result)", + "event FheRand(bytes1 randType, uint256 result)", + "event FheRandBounded(uint256 upperBound, bytes1 randType, uint256 result)", +]; + +async function processAllPastTFHEExecutorEvents() { + const latestBlockNumber = await provider.getBlockNumber(); + + const contract = new ethers.Contract(executorAddress, abi, provider); + + // Fetch all events emitted by the contract + const filter = { + address: executorAddress, + fromBlock: firstBlockListening, + toBlock: latestBlockNumber, + }; + + const logs = await provider.getLogs(filter); + + const events = logs + .map((log) => { + try { + const parsedLog = contract.interface.parseLog(log); + return { + eventName: parsedLog.name, + args: parsedLog.args, + }; + } catch (e) { + // If the log cannot be parsed, skip it + return null; + } + }) + .filter((event) => event !== null); + + firstBlockListening = latestBlockNumber + 1; + + events.map(async (event) => await insertHandleFromEvent(event)); +} + +async function insertHandleFromEvent(event: FHEVMEvent) { + let handle; + let clearText; + let clearLHS; + let clearRHS; + let resultType; + let shift; + + switch (event.eventName) { + case "TrivialEncrypt": + clearText = event.args[0]; + handle = ethers.toBeHex(event.args[2], 32); + insertSQL(handle, clearText); + break; + + case "TrivialEncryptBytes": + clearText = event.args[0]; + handle = ethers.toBeHex(event.args[2], 32); + insertSQL(handle, clearText); + break; + + case "FheAdd": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) + event.args[1]; + clearText = clearText % 2n ** NumBits[resultType]; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) + BigInt(clearRHS); + clearText = clearText % 2n ** NumBits[resultType]; + } + insertSQL(ethers.toBeHex(handle, 32), clearText); + break; + + case "FheSub": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) - event.args[1]; + if (clearText < 0n) clearText = clearText + 2n ** NumBits[resultType]; + clearText = clearText % 2n ** NumBits[resultType]; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) - BigInt(clearRHS); + if (clearText < 0n) clearText = clearText + 2n ** NumBits[resultType]; + clearText = clearText % 2n ** NumBits[resultType]; + } + insertSQL(handle, clearText); + break; + + case "FheMul": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) * event.args[1]; + clearText = clearText % 2n ** NumBits[resultType]; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) * BigInt(clearRHS); + clearText = clearText % 2n ** NumBits[resultType]; + } + insertSQL(handle, clearText); + break; + + case "FheDiv": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) / event.args[1]; + } else { + throw new Error("Non-scalar div not implemented yet"); + } + insertSQL(handle, clearText); + break; + + case "FheRem": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) % event.args[1]; + } else { + throw new Error("Non-scalar rem not implemented yet"); + } + insertSQL(handle, clearText); + break; + + case "FheBitAnd": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) & event.args[1]; + clearText = clearText % 2n ** NumBits[resultType]; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) & BigInt(clearRHS); + clearText = clearText % 2n ** NumBits[resultType]; + } + insertSQL(handle, clearText); + break; + + case "FheBitOr": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) | event.args[1]; + clearText = clearText % 2n ** NumBits[resultType]; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) | BigInt(clearRHS); + clearText = clearText % 2n ** NumBits[resultType]; + } + insertSQL(handle, clearText); + break; + + case "FheBitXor": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) ^ event.args[1]; + clearText = clearText % 2n ** NumBits[resultType]; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) ^ BigInt(clearRHS); + clearText = clearText % 2n ** NumBits[resultType]; + } + insertSQL(handle, clearText); + break; + + case "FheShl": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) << event.args[1] % NumBits[resultType]; + clearText = clearText % 2n ** NumBits[resultType]; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) << BigInt(clearRHS) % NumBits[resultType]; + clearText = clearText % 2n ** NumBits[resultType]; + } + insertSQL(handle, clearText); + break; + + case "FheShr": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) >> event.args[1] % NumBits[resultType]; + clearText = clearText % 2n ** NumBits[resultType]; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) >> BigInt(clearRHS) % NumBits[resultType]; + clearText = clearText % 2n ** NumBits[resultType]; + } + insertSQL(handle, clearText); + break; + + case "FheRotl": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + shift = event.args[1] % NumBits[resultType]; + clearText = (BigInt(clearLHS) << shift) | (BigInt(clearLHS) >> (NumBits[resultType] - shift)); + clearText = clearText % 2n ** NumBits[resultType]; + } else { + clearRHS = await getClearText(event.args[1]); + shift = BigInt(clearRHS) % NumBits[resultType]; + clearText = (BigInt(clearLHS) << shift) | (BigInt(clearLHS) >> (NumBits[resultType] - shift)); + clearText = clearText % 2n ** NumBits[resultType]; + } + insertSQL(handle, clearText); + break; + + case "FheRotr": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + shift = event.args[1] % NumBits[resultType]; + clearText = (BigInt(clearLHS) >> shift) | (BigInt(clearLHS) << (NumBits[resultType] - shift)); + clearText = clearText % 2n ** NumBits[resultType]; + } else { + clearRHS = await getClearText(event.args[1]); + shift = BigInt(clearRHS) % NumBits[resultType]; + clearText = (BigInt(clearLHS) >> shift) | (BigInt(clearLHS) << (NumBits[resultType] - shift)); + clearText = clearText % 2n ** NumBits[resultType]; + } + insertSQL(handle, clearText); + break; + + case "FheEq": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) === event.args[1] ? 1n : 0n; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) === BigInt(clearRHS) ? 1n : 0n; + } + insertSQL(handle, clearText); + break; + + case "FheEqBytes": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) === BigInt(event.args[1]) ? 1n : 0n; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) === BigInt(clearRHS) ? 1n : 0n; + } + insertSQL(handle, clearText); + break; + + case "FheNe": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) !== event.args[1] ? 1n : 0n; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) !== BigInt(clearRHS) ? 1n : 0n; + } + insertSQL(handle, clearText); + break; + + case "FheNeBytes": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) !== BigInt(event.args[1]) ? 1n : 0n; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) !== BigInt(clearRHS) ? 1n : 0n; + } + insertSQL(handle, clearText); + break; + + case "FheGe": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) >= event.args[1] ? 1n : 0n; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) >= BigInt(clearRHS) ? 1n : 0n; + } + insertSQL(handle, clearText); + break; + + case "FheGt": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) > event.args[1] ? 1n : 0n; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) > BigInt(clearRHS) ? 1n : 0n; + } + insertSQL(handle, clearText); + break; + + case "FheLe": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) <= event.args[1] ? 1n : 0n; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) <= BigInt(clearRHS) ? 1n : 0n; + } + insertSQL(handle, clearText); + break; + + case "FheLt": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) < event.args[1] ? 1n : 0n; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) < BigInt(clearRHS) ? 1n : 0n; + } + insertSQL(handle, clearText); + break; + + case "FheMax": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) > event.args[1] ? clearLHS : event.args[1]; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) > BigInt(clearRHS) ? clearLHS : clearRHS; + } + insertSQL(handle, clearText); + break; + + case "FheMin": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) < event.args[1] ? clearLHS : event.args[1]; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) < BigInt(clearRHS) ? clearLHS : clearRHS; + } + insertSQL(handle, clearText); + break; + + case "Cast": + resultType = parseInt(event.args[1]); + handle = ethers.toBeHex(event.args[2], 32); + clearText = BigInt(await getClearText(event.args[0])) % 2n ** NumBits[resultType]; + insertSQL(handle, clearText); + break; + + case "FheNot": + handle = ethers.toBeHex(event.args[1], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearText = BigInt(await getClearText(event.args[0])); + clearText = bitwiseNotUintBits(clearText, Number(NumBits[resultType])); + insertSQL(handle, clearText); + break; + + case "FheNeg": + handle = ethers.toBeHex(event.args[1], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearText = BigInt(await getClearText(event.args[0])); + clearText = bitwiseNotUintBits(clearText, Number(NumBits[resultType])); + clearText = (clearText + 1n) % 2n ** NumBits[resultType]; + insertSQL(handle, clearText); + break; + + case "VerifyCiphertext": + handle = event.args[0]; + try { + await getClearText(BigInt(handle)); + } catch { + throw Error("User input was not found in DB"); + } + break; + + case "FheIfThenElse": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + handle = ethers.toBeHex(event.args[3], 32); + const clearControl = BigInt(await getClearText(event.args[0])); + const clearIfTrue = BigInt(await getClearText(event.args[1])); + const clearIfFalse = BigInt(await getClearText(event.args[2])); + if (clearControl === 1n) { + clearText = clearIfTrue; + } else { + clearText = clearIfFalse; + } + insertSQL(handle, clearText); + break; + + case "FheRand": + resultType = parseInt(event.args[0], 16); + handle = ethers.toBeHex(event.args[1], 32); + clearText = getRandomBigInt(Number(NumBits[resultType])); + insertSQL(handle, clearText, true); + counterRand++; + break; + + case "FheRandBounded": + resultType = parseInt(event.args[1], 16); + handle = ethers.toBeHex(event.args[2], 32); + clearText = getRandomBigInt(Number(log2(BigInt(event.args[0])))); + insertSQL(handle, clearText, true); + counterRand++; + break; + } +} diff --git a/hardhat/mockedServices/server.ts b/hardhat/mockedServices/server.ts new file mode 100644 index 0000000..437fb5b --- /dev/null +++ b/hardhat/mockedServices/server.ts @@ -0,0 +1,418 @@ +import { toBufferBE } from "bigint-buffer"; +import cors from "cors"; +import crypto from "crypto"; +import { JsonRpcProvider, Wallet, ethers } from "ethers"; +import express, { Request, Response } from "express"; +import { Keccak } from "sha3"; + +import { + ACL_ADDRESS, + INPUTVERIFIER_ADDRESS, + KMSVERIFIER_ADDRESS, + PRIVATE_KEY_COPROCESSOR_ACCOUNT, + PRIVATE_KEY_KMS_SIGNER, +} from "../test/constants"; +import { initGateway } from "./asyncDecrypt"; +import { awaitCoprocessor, getClearText, insertSQL } from "./coprocessorUtils"; + +const provider = new JsonRpcProvider("http://127.0.0.1:8545"); + +enum Types { + ebool = 0, + euint4, + euint8, + euint16, + euint32, + euint64, + euint128, + eaddress, + euint256, + ebytes64, + ebytes128, + ebytes256, +} + +interface ApiSuccessResponse { + status: "success"; + result: string; +} + +interface ApiErrorResponse { + status: "error"; + message: string; +} + +function numberToHex(num: number) { + const hex = num.toString(16); + return hex.length % 2 ? "0" + hex : hex; +} + +function uint8ArrayToHexString(uint8Array: Uint8Array) { + return Array.from(uint8Array) + .map((byte) => byte.toString(16).padStart(2, "0")) + .join(""); +} + +type ApiResponse = ApiSuccessResponse | ApiErrorResponse; + +const app = express(); +app.use(cors()); +app.use(express.json()); +const port = 3000; + +app.post("/get-clear-text", async (req: Request, res: Response) => { + try { + const { handle } = req.body; + + if (!handle || typeof handle !== "string") { + return res.status(400).json({ + status: "error", + message: "Handle must be provided as a string", + }); + } + + let bigintHandle: bigint; + try { + bigintHandle = BigInt(handle); + } catch (error) { + return res.status(400).json({ + status: "error", + message: "Invalid bigint format", + }); + } + + await awaitCoprocessor(); + const result = await getClearText(bigintHandle); + + res.json({ + status: "success", + result, + }); + } catch (error) { + const errorMessage = error instanceof Error ? error.message : "Unknown error occurred"; + res.status(500).json({ + status: "error", + message: errorMessage, + }); + } +}); + +export const ENCRYPTION_TYPES = { + 2: 0, + 4: 1, + 8: 2, + 16: 3, + 32: 4, + 64: 5, + 128: 6, + 160: 7, + 256: 8, + 512: 9, + 1024: 10, + 2048: 11, +}; + +type EncryptionKey = keyof typeof ENCRYPTION_TYPES; + +interface EncryptRequest { + values: string[]; + bits: EncryptionKey[]; +} + +interface EncryptResponse { + status: "success" | "error"; + handles?: Uint8Array[]; + inputProof?: string; + message?: string; +} + +async function encrypt( + values: bigint[], + bits: EncryptionKey[], + userAddress: string, + contractAddress: string, +): Promise<{ handles: string[]; inputProof: string }> { + let encrypted = Buffer.alloc(0); + + bits.map((v, i) => { + encrypted = Buffer.concat([encrypted, createUintToUint8ArrayFunction(v)(values[i])]); + }); + + const encryptedArray = new Uint8Array(encrypted); + const hash = new Keccak(256).update(Buffer.from(encryptedArray)).digest(); + + const handles = bits.map((v, i) => { + const dataWithIndex = new Uint8Array(hash.length + 1); + dataWithIndex.set(hash, 0); + dataWithIndex.set([i], hash.length); + const finalHash = new Keccak(256).update(Buffer.from(dataWithIndex)).digest(); + const dataInput = new Uint8Array(32); + dataInput.set(finalHash, 0); + dataInput.set([i, ENCRYPTION_TYPES[v], 0], 29); + return dataInput; + }); + let inputProof = "0x" + numberToHex(handles.length); // for coprocessor : numHandles + numSignersKMS + hashCT + list_handles + signatureCopro + signatureKMSSigners (total len : 1+1+32+NUM_HANDLES*32+65+65*numSignersKMS) + const numSigners = 1; // @note: only 1 signer in mocked mode for the moment + inputProof += numberToHex(numSigners); + inputProof += hash.toString("hex"); + + const listHandlesStr = handles.map((i) => uint8ArrayToHexString(i)); + listHandlesStr.map((handle) => (inputProof += handle)); + const listHandles = listHandlesStr.map((i) => BigInt("0x" + i)); + const sigCoproc = await computeInputSignatureCopro( + "0x" + hash.toString("hex"), + listHandles, + userAddress, + contractAddress, + ); + inputProof += sigCoproc.slice(2); + + const signaturesKMS = await computeInputSignaturesKMS("0x" + hash.toString("hex"), userAddress, contractAddress); + signaturesKMS.map((sigKMS) => (inputProof += sigKMS.slice(2))); + listHandlesStr.map((handle, i) => insertSQL("0x" + handle, values[i])); + return { + handles: listHandlesStr.map((i) => "0x" + i), + inputProof, + }; +} + +app.post("/encrypt", async (req: Request<{}, {}, EncryptRequest>, res: Response) => { + try { + const { values, bits, userAddress, contractAddress } = req.body; + + const bigintValues: bigint[] = []; + + for (const value of values) { + bigintValues.push(BigInt(value)); + } + const result = await encrypt(bigintValues, bits, userAddress, contractAddress); + + res.json({ + status: "success", + handles: result.handles, + inputProof: result.inputProof, + }); + } catch (error) { + const errorMessage = error instanceof Error ? error.message : "Unknown error occurred"; + res.status(500).json({ + status: "error", + message: errorMessage, + }); + } +}); + +function createUintToUint8ArrayFunction(numBits: number) { + const numBytes = Math.ceil(numBits / 8); + return function (uint: number | bigint | boolean) { + const buffer = toBufferBE(BigInt(uint), numBytes); + + // concatenate 32 random bytes at the end of buffer to simulate encryption noise + const randomBytes = crypto.randomBytes(32); + const combinedBuffer = Buffer.concat([buffer, randomBytes]); + + let byteBuffer; + let totalBuffer; + + switch (numBits) { + case 2: // ebool takes 2 bits + byteBuffer = Buffer.from([Types.ebool]); + totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); + break; + case 4: + byteBuffer = Buffer.from([Types.euint4]); + totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); + break; + case 8: + byteBuffer = Buffer.from([Types.euint8]); + totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); + break; + case 16: + byteBuffer = Buffer.from([Types.euint16]); + totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); + break; + case 32: + byteBuffer = Buffer.from([Types.euint32]); + totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); + break; + case 64: + byteBuffer = Buffer.from([Types.euint64]); + totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); + break; + case 128: + byteBuffer = Buffer.from([Types.euint128]); + totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); + break; + case 160: + byteBuffer = Buffer.from([Types.eaddress]); + totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); + break; + case 256: + byteBuffer = Buffer.from([Types.euint256]); + totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); + break; + case 512: + byteBuffer = Buffer.from([Types.ebytes64]); + totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); + break; + case 1024: + byteBuffer = Buffer.from([Types.ebytes128]); + totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); + break; + case 2048: + byteBuffer = Buffer.from([Types.ebytes256]); + totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); + break; + default: + throw Error("Non-supported numBits"); + } + + return totalBuffer; + }; +} + +async function computeInputSignatureCopro( + hash: string, + handlesList: bigint[], + userAddress: string, + contractAddress: string, +): Promise { + const privKeySigner = PRIVATE_KEY_COPROCESSOR_ACCOUNT; + const coprocSigner = new Wallet(privKeySigner).connect(provider); + const signature = await coprocSign(hash, handlesList, userAddress, contractAddress, coprocSigner); + return signature; +} + +async function computeInputSignaturesKMS( + hash: string, + userAddress: string, + contractAddress: string, +): Promise { + const signatures: string[] = []; + const numSigners = 1; // @note: only 1 KMS signer in mocked mode for now + for (let idx = 0; idx < numSigners; idx++) { + const privKeySigner = PRIVATE_KEY_KMS_SIGNER; + const kmsSigner = new ethers.Wallet(privKeySigner).connect(provider); + const signature = await kmsSign(hash, userAddress, contractAddress, kmsSigner); + signatures.push(signature); + } + return signatures; +} + +async function coprocSign( + hashOfCiphertext: string, + handlesList: bigint[], + userAddress: string, + contractAddress: string, + signer: Wallet, +): Promise { + const inputAdd = INPUTVERIFIER_ADDRESS; + const chainId = 31337; + const aclAdd = ACL_ADDRESS; + + const domain = { + name: "InputVerifier", + version: "1", + chainId: chainId, + verifyingContract: inputAdd, + }; + + const types = { + CiphertextVerificationForCopro: [ + { + name: "aclAddress", + type: "address", + }, + { + name: "hashOfCiphertext", + type: "bytes32", + }, + { + name: "handlesList", + type: "uint256[]", + }, + { + name: "userAddress", + type: "address", + }, + { + name: "contractAddress", + type: "address", + }, + ], + }; + const message = { + aclAddress: aclAdd, + hashOfCiphertext: hashOfCiphertext, + handlesList: handlesList, + userAddress: userAddress, + contractAddress: contractAddress, + }; + + const signature = await signer.signTypedData(domain, types, message); + const sigRSV = ethers.Signature.from(signature); + const v = 27 + sigRSV.yParity; + const r = sigRSV.r; + const s = sigRSV.s; + + const result = r + s.substring(2) + v.toString(16); + return result; +} + +async function kmsSign( + hashOfCiphertext: string, + userAddress: string, + contractAddress: string, + signer: Wallet, +): Promise { + const kmsVerifierAdd = KMSVERIFIER_ADDRESS; + const chainId = 31337; + const aclAdd = ACL_ADDRESS; + + const domain = { + name: "KMSVerifier", + version: "1", + chainId: chainId, + verifyingContract: kmsVerifierAdd, + }; + + const types = { + CiphertextVerificationForKMS: [ + { + name: "aclAddress", + type: "address", + }, + { + name: "hashOfCiphertext", + type: "bytes32", + }, + { + name: "userAddress", + type: "address", + }, + { + name: "contractAddress", + type: "address", + }, + ], + }; + const message = { + aclAddress: aclAdd, + hashOfCiphertext: hashOfCiphertext, + userAddress: userAddress, + contractAddress: contractAddress, + }; + + const signature = await signer.signTypedData(domain, types, message); + const sigRSV = ethers.Signature.from(signature); + const v = 27 + sigRSV.yParity; + const r = sigRSV.r; + const s = sigRSV.s; + + const result = r + s.substring(2) + v.toString(16); + return result; +} + +app.listen(port, async () => { + console.log(`Server running at http://localhost:${port}`); + await initGateway(); +}); diff --git a/hardhat/package.json b/hardhat/package.json new file mode 100644 index 0000000..7bacc5a --- /dev/null +++ b/hardhat/package.json @@ -0,0 +1,100 @@ +{ + "name": "@zama-ai/fhevm-hardhat-template", + "description": "fhEVM hardhat template", + "version": "1.0.0", + "engines": { + "node": ">=20.0.0" + }, + "author": { + "name": "zama-ai", + "url": "https://github.com/zama-ai" + }, + "devDependencies": { + "@eslint/js": "^9.9.0", + "@nomicfoundation/hardhat-chai-matchers": "^2.0.0", + "@nomicfoundation/hardhat-ethers": "^3.0.0", + "@nomicfoundation/hardhat-network-helpers": "^1.0.6", + "@nomicfoundation/hardhat-toolbox": "^5.0.0", + "@nomicfoundation/hardhat-verify": "^2.0.12", + "@openzeppelin/contracts": "^5.1.0", + "@openzeppelin/hardhat-upgrades": "^3.6.0", + "@trivago/prettier-plugin-sort-imports": "^4.0.0", + "@typechain/ethers-v6": "^0.5.1", + "@typechain/hardhat": "^9.1.0", + "@types/chai": "^4.3.4", + "@types/eslint__js": "^8.42.3", + "@types/fs-extra": "^9.0.13", + "@types/mocha": "^10.0.0", + "@types/node": "^18.19.59", + "@typescript-eslint/eslint-plugin": "^8.0.1", + "@typescript-eslint/parser": "^8.0.1", + "chai": "^4.3.7", + "cors": "^2.8.5", + "cross-env": "^7.0.3", + "dotenv": "^16.0.3", + "eslint": "^9.9.0", + "eslint-config-prettier": "^8.5.0", + "ethers": "^6.8.0", + "express": "^4.21.2", + "extra-bigint": "^1.1.18", + "fhevm": "^0.6.1", + "fhevm-contracts": "^0.2.1", + "fhevm-core-contracts": "^0.6.1", + "fhevmjs": "^0.6.1", + "fs-extra": "^10.1.0", + "globals": "^15.9.0", + "hardhat": "^2.22.8", + "hardhat-deploy": "^0.12.4", + "hardhat-gas-reporter": "^1.0.9", + "hardhat-ignore-warnings": "^0.2.11", + "hardhat-preprocessor": "^0.1.5", + "lodash": "^4.17.21", + "mocha": "^10.1.0", + "prettier": "^2.8.4", + "prettier-plugin-solidity": "^1.1.2", + "rimraf": "^4.1.2", + "sha3": "^2.1.4", + "solhint": "^3.4.0", + "solhint-plugin-prettier": "^0.0.5", + "solidity-coverage": "0.8.12", + "sqlite3": "^5.1.7", + "ts-generator": "^0.1.1", + "ts-node": "^10.9.1", + "typechain": "^8.2.0", + "typescript": "^5.5.4", + "typescript-eslint": "^8.0.1", + "web3-validator": "^2.0.6" + }, + "files": [ + "contracts" + ], + "keywords": [ + "blockchain", + "ethers", + "ethereum", + "hardhat", + "smart-contracts", + "solidity", + "template", + "typescript", + "typechain" + ], + "publishConfig": { + "access": "public" + }, + "scripts": { + "clean": "rimraf ./artifacts ./cache ./coverage ./types ./coverage.json && pnpm typechain", + "compile": "cross-env TS_NODE_TRANSPILE_ONLY=true hardhat compile", + "lint": "pnpm lint:sol && pnpm lint:ts && pnpm prettier:check", + "lint:sol": "solhint --max-warnings 25 \"contracts/**/*.sol\"", + "lint:ts": "eslint .", + "postinstall": "DOTENV_CONFIG_PATH=./.env.example pnpm typechain", + "prettier:check": "prettier --check \"**/*.{js,json,md,sol,ts,yml}\"", + "prettier:write": "prettier --write \"**/*.{js,json,md,sol,ts,yml}\"", + "typechain": "cross-env TS_NODE_TRANSPILE_ONLY=true hardhat typechain", + "test": "hardhat test --network hardhat", + "coverage": "hardhat coverage", + "deploy-sepolia": "hardhat deploy --network sepolia", + "mint-sepolia": "hardhat mint --amount 42 --network sepolia" + } +} diff --git a/hardhat/tasks/accounts.ts b/hardhat/tasks/accounts.ts new file mode 100644 index 0000000..2ca9e7a --- /dev/null +++ b/hardhat/tasks/accounts.ts @@ -0,0 +1,39 @@ +import { task, types } from "hardhat/config"; + +import { ACCOUNT_NAMES } from "../test/constants"; + +task("get-accounts", "Prints the list of accounts") + .addParam("numAccounts", "Number of accounts to return (1-10)", 3, types.int) + .setAction(async ({ numAccounts }, hre) => { + // Validate input + if (numAccounts < 1 || numAccounts > 10) { + throw new Error("Number of accounts must be between 1 and 10"); + } + + // Get signers from hardhat + const signers = await hre.ethers.getSigners(); + const accounts = []; + const { mnemonic } = hre.network.config.accounts; + + // Get details for specified number of accounts + for (let i = 0; i < numAccounts && i < signers.length; i++) { + const signer = signers[i]; + const address = await signer.getAddress(); + const phrase = hre.ethers.Mnemonic.fromPhrase(mnemonic); + const pathDeployer = "m/44'/60'/0'/0/" + i; + const privateKey = hre.ethers.HDNodeWallet.fromMnemonic(phrase, pathDeployer).privateKey; + + accounts.push({ + index: i, + privateKey: privateKey, + address: address, + }); + } + console.info("\nAccount Details:"); + console.info("================"); + accounts.forEach(({ index, privateKey, address }) => { + console.info(`\nAccount ${index}: (${ACCOUNT_NAMES[index]})`); + console.info(`Address: ${address}`); + console.info(`Private Key: ${privateKey}`); + }); + }); diff --git a/hardhat/tasks/etherscanVerify.ts b/hardhat/tasks/etherscanVerify.ts new file mode 100644 index 0000000..55e60b4 --- /dev/null +++ b/hardhat/tasks/etherscanVerify.ts @@ -0,0 +1,65 @@ +import { task } from "hardhat/config"; + +task("verify-deployed", "Verifies an already deployed contract on Etherscan") + .addParam("address", "The contract's address") + .addParam("contract", "Full contract path (e.g., 'contracts/MyConfidentialERC20.sol:MyConfidentialERC20.sol')") + .addParam("args", "Constructor arguments as comma-separated values", "") + .setAction(async (taskArgs, hre) => { + if (hre.network.name === "hardhat") { + throw Error("Etherscan verification is not possilbe in mocked mode, choose another network"); + } + const { address, contract, args } = taskArgs; + + console.info("\nStarting verification for deployed contract..."); + console.info("Contract:", contract); + console.info("Address:", address); + + try { + // Parse constructor arguments + const constructorArgs = args + ? args.split(",").map((arg) => { + const trimmed = arg.trim(); + // Try to parse as JSON + try { + return JSON.parse(trimmed); + } catch { + // If it's a number + if (!isNaN(trimmed)) { + return Number(trimmed); + } + // If it's a boolean + if (trimmed.toLowerCase() === "true") return true; + if (trimmed.toLowerCase() === "false") return false; + // Otherwise return as string + return trimmed; + } + }) + : []; + + console.info("Constructor Arguments:", constructorArgs); + + // Prepare verification arguments + const verificationArgs = { + address: address, + contract: contract, + constructorArguments: constructorArgs, + }; + + console.info("\nSubmitting verification request..."); + await hre.run("verify:verify", verificationArgs); + + console.info("\n✅ Contract verification completed successfully!"); + } catch (error) { + if (error.message.includes("Already Verified")) { + console.info("\n✓ Contract is already verified!"); + } else { + console.error("\n❌ Verification failed:", error.message); + console.info("\nTo verify your contract, use the following format:"); + console.info("\nnpx hardhat verify-deployed \\"); + console.info(" --address", address, "\\"); + console.info(" --contract", contract, "\\"); + console.info(' --args "arg1,arg2,arg3" \\'); + console.info(" --network "); + } + } + }); diff --git a/hardhat/tasks/mintMyConfidentialERC20.ts b/hardhat/tasks/mintMyConfidentialERC20.ts new file mode 100644 index 0000000..7008271 --- /dev/null +++ b/hardhat/tasks/mintMyConfidentialERC20.ts @@ -0,0 +1,18 @@ +import { task } from "hardhat/config"; +import type { TaskArguments } from "hardhat/types"; +import { HardhatRuntimeEnvironment } from "hardhat/types"; + +import { MyConfidentialERC20 } from "../types"; + +task("mint") + .addParam("amount", "Tokens to mint") + .setAction(async function (taskArguments: TaskArguments, hre: HardhatRuntimeEnvironment) { + const { ethers, deployments } = hre; + const ERC20 = await deployments.get("MyConfidentialERC20"); + const signers = await ethers.getSigners(); + const erc20 = (await ethers.getContractAt("MyConfidentialERC20", ERC20.address)) as MyConfidentialERC20; + const tx = await erc20.connect(signers[0]).mint(+taskArguments.amount); + const rcpt = await tx.wait(); + console.info("Mint tx hash: ", rcpt!.hash); + console.info("Mint done: ", taskArguments.amount, "tokens were minted succesfully"); + }); diff --git a/hardhat/test/asyncDecrypt.ts b/hardhat/test/asyncDecrypt.ts new file mode 100644 index 0000000..42ba470 --- /dev/null +++ b/hardhat/test/asyncDecrypt.ts @@ -0,0 +1,227 @@ +import { Wallet, ZeroAddress } from "ethers"; +import gatewayArtifact from "fhevm-core-contracts/artifacts/gateway/GatewayContract.sol/GatewayContract.json"; +import { ethers, network } from "hardhat"; + +import { ACL_ADDRESS, GATEWAYCONTRACT_ADDRESS, KMSVERIFIER_ADDRESS, PRIVATE_KEY_KMS_SIGNER } from "./constants"; +import { awaitCoprocessor, getClearText } from "./coprocessorUtils"; +import { impersonateAddress } from "./mockedSetup"; +import { waitNBlocks } from "./utils"; + +const networkName = network.name; +const aclAdd = ACL_ADDRESS; + +const CiphertextType = { + 0: "bool", + 1: "uint8", // corresponding to euint4 + 2: "uint8", // corresponding to euint8 + 3: "uint16", + 4: "uint32", + 5: "uint64", + 6: "uint128", + 7: "address", + 8: "uint256", + 9: "bytes", + 10: "bytes", + 11: "bytes", +}; + +const currentTime = (): string => { + const now = new Date(); + return now.toLocaleTimeString("en-US", { hour12: true, hour: "numeric", minute: "numeric", second: "numeric" }); +}; + +const argEvents = + "(uint256 indexed requestID, uint256[] cts, address contractCaller, bytes4 callbackSelector, uint256 msgValue, uint256 maxTimestamp, bool passSignaturesToCaller)"; +const ifaceEventDecryption = new ethers.Interface(["event EventDecryption" + argEvents]); + +const argEvents2 = "(uint256 indexed requestID, bool success, bytes result)"; +const ifaceResultCallback = new ethers.Interface(["event ResultCallback" + argEvents2]); + +let gateway; +let firstBlockListening: number; +let lastBlockSnapshotForDecrypt: number; + +export const initGateway = async (): Promise => { + firstBlockListening = await ethers.provider.getBlockNumber(); + if (networkName === "hardhat" && hre.__SOLIDITY_COVERAGE_RUNNING !== true) { + // evm_snapshot is not supported in coverage mode + await ethers.provider.send("set_lastBlockSnapshotForDecrypt", [firstBlockListening]); + } + // this function will emit logs for every request and fulfilment of a decryption + gateway = await ethers.getContractAt(gatewayArtifact.abi, GATEWAYCONTRACT_ADDRESS); + gateway.on( + "EventDecryption", + async (requestID, cts, contractCaller, callbackSelector, msgValue, maxTimestamp, eventData) => { + const blockNumber = eventData.log.blockNumber; + console.log(`${await currentTime()} - Requested decrypt on block ${blockNumber} (requestID ${requestID})`); + }, + ); + gateway.on("ResultCallback", async (requestID, success, result, eventData) => { + const blockNumber = eventData.log.blockNumber; + console.log(`${await currentTime()} - Fulfilled decrypt on block ${blockNumber} (requestID ${requestID})`); + }); +}; + +export const awaitAllDecryptionResults = async (): Promise => { + gateway = await ethers.getContractAt(gatewayArtifact.abi, GATEWAYCONTRACT_ADDRESS); + const provider = ethers.provider; + if (networkName === "hardhat" && hre.__SOLIDITY_COVERAGE_RUNNING !== true) { + // evm_snapshot is not supported in coverage mode + lastBlockSnapshotForDecrypt = await provider.send("get_lastBlockSnapshotForDecrypt"); + if (lastBlockSnapshotForDecrypt < firstBlockListening) { + firstBlockListening = lastBlockSnapshotForDecrypt + 1; + } + } + await fulfillAllPastRequestsIds(networkName === "hardhat"); + firstBlockListening = (await ethers.provider.getBlockNumber()) + 1; + if (networkName === "hardhat" && hre.__SOLIDITY_COVERAGE_RUNNING !== true) { + // evm_snapshot is not supported in coverage mode + await provider.send("set_lastBlockSnapshotForDecrypt", [firstBlockListening]); + } +}; + +const getAlreadyFulfilledDecryptions = async (): Promise<[bigint]> => { + let results = []; + const eventDecryptionResult = await gateway.filters.ResultCallback().getTopicFilter(); + const filterDecryptionResult = { + address: GATEWAYCONTRACT_ADDRESS, + fromBlock: firstBlockListening, + toBlock: "latest", + topics: eventDecryptionResult, + }; + const pastResults = await ethers.provider.getLogs(filterDecryptionResult); + results = results.concat(pastResults.map((result) => ifaceResultCallback.parseLog(result).args[0])); + return results; +}; + +const allTrue = (arr: boolean[], fn = Boolean) => arr.every(fn); + +const fulfillAllPastRequestsIds = async (mocked: boolean) => { + const eventDecryption = await gateway.filters.EventDecryption().getTopicFilter(); + const results = await getAlreadyFulfilledDecryptions(); + const filterDecryption = { + address: GATEWAYCONTRACT_ADDRESS, + fromBlock: firstBlockListening, + toBlock: "latest", + topics: eventDecryption, + }; + const pastRequests = await ethers.provider.getLogs(filterDecryption); + for (const request of pastRequests) { + const event = ifaceEventDecryption.parseLog(request); + const requestID = event.args[0]; + const handles = event.args[1]; + const typesList = handles.map((handle) => parseInt(handle.toString(16).slice(-4, -2), 16)); + const msgValue = event.args[4]; + + if (!results.includes(requestID)) { + // if request is not already fulfilled + if (mocked) { + // in mocked mode, we trigger the decryption fulfillment manually + await awaitCoprocessor(); + + // first check tat all handles are allowed for decryption + const aclArtifact = require("fhevm-core-contracts/artifacts/contracts/ACL.sol/ACL.json"); + const acl = await ethers.getContractAt(aclArtifact.abi, ACL_ADDRESS); + const isAllowedForDec = await Promise.all(handles.map(async (handle) => acl.isAllowedForDecryption(handle))); + if (!allTrue(isAllowedForDec)) { + throw new Error("Some handle is not authorized for decryption"); + } + const types = typesList.map((num) => CiphertextType[num]); + const values = await Promise.all(handles.map(async (handle) => BigInt(await getClearText(handle)))); + const valuesFormatted = values.map((value, index) => + types[index] === "address" ? "0x" + value.toString(16).padStart(40, "0") : value, + ); + const valuesFormatted2 = valuesFormatted.map((value, index) => + typesList[index] === 9 ? "0x" + value.toString(16).padStart(128, "0") : value, + ); + const valuesFormatted3 = valuesFormatted2.map((value, index) => + typesList[index] === 10 ? "0x" + value.toString(16).padStart(256, "0") : value, + ); + const valuesFormatted4 = valuesFormatted3.map((value, index) => + typesList[index] === 11 ? "0x" + value.toString(16).padStart(512, "0") : value, + ); + + const abiCoder = new ethers.AbiCoder(); + let encodedData; + let calldata; + + encodedData = abiCoder.encode(["uint256", ...types], [31, ...valuesFormatted4]); // 31 is just a dummy uint256 requestID to get correct abi encoding for the remaining arguments (i.e everything except the requestID) + calldata = "0x" + encodedData.slice(66); // we just pop the dummy requestID to get the correct value to pass for `decryptedCts` + + const numSigners = 1; // for the moment mocked mode only uses 1 signer + const decryptResultsEIP712signatures = await computeDecryptSignatures(handles, calldata, numSigners); + const relayer = await impersonateAddress(hre, ZeroAddress, ethers.parseEther("100")); + await gateway + .connect(relayer) + .fulfillRequest(requestID, calldata, decryptResultsEIP712signatures, { value: msgValue }); + } else { + // in non-mocked mode we must wait until the gateway service relayer submits the decryption fulfillment tx + await waitNBlocks(1); + await fulfillAllPastRequestsIds(mocked); + } + } + } +}; + +async function computeDecryptSignatures( + handlesList: bigint[], + decryptedResult: string, + numSigners: number, +): Promise { + const signatures: string[] = []; + + for (let idx = 0; idx < numSigners; idx++) { + const privKeySigner = PRIVATE_KEY_KMS_SIGNER; + if (privKeySigner) { + const kmsSigner = new ethers.Wallet(privKeySigner).connect(ethers.provider); + const signature = await kmsSign(handlesList, decryptedResult, kmsSigner); + signatures.push(signature); + } else { + throw new Error(`Private key for signer ${idx} not found in environment variables`); + } + } + return signatures; +} + +async function kmsSign(handlesList: bigint[], decryptedResult: string, kmsSigner: Wallet) { + const kmsAdd = KMSVERIFIER_ADDRESS; + const chainId = (await ethers.provider.getNetwork()).chainId; + + const domain = { + name: "KMSVerifier", + version: "1", + chainId: chainId, + verifyingContract: kmsAdd, + }; + + const types = { + DecryptionResult: [ + { + name: "aclAddress", + type: "address", + }, + { + name: "handlesList", + type: "uint256[]", + }, + { + name: "decryptedResult", + type: "bytes", + }, + ], + }; + const message = { + aclAddress: aclAdd, + handlesList: handlesList, + decryptedResult: decryptedResult, + }; + + const signature = await kmsSigner.signTypedData(domain, types, message); + const sigRSV = ethers.Signature.from(signature); + const v = 27 + sigRSV.yParity; + const r = sigRSV.r; + const s = sigRSV.s; + + const result = r + s.substring(2) + v.toString(16); + return result; +} diff --git a/hardhat/test/confidentialCounter/sample1.ts b/hardhat/test/confidentialCounter/sample1.ts new file mode 100644 index 0000000..8ffbeef --- /dev/null +++ b/hardhat/test/confidentialCounter/sample1.ts @@ -0,0 +1,25 @@ +import { ethers } from "hardhat"; + +import { createInstance } from "../instance"; +import { getSigners, initSigners } from "../signers"; + +describe("EncryptedCounter1", function () { + before(async function () { + await initSigners(); // Initialize signers + this.signers = await getSigners(); + }); + + beforeEach(async function () { + const CounterFactory = await ethers.getContractFactory("EncryptedCounter1"); + this.counterContract = await CounterFactory.connect(this.signers.alice).deploy(); + await this.counterContract.waitForDeployment(); + this.contractAddress = await this.counterContract.getAddress(); + this.instances = await createInstance(); + }); + + it("should increment the counter", async function () { + // Perform the increment action + const tx = await this.counterContract.increment(); + await tx.wait(); + }); +}); diff --git a/hardhat/test/confidentialCounter/sample2.ts b/hardhat/test/confidentialCounter/sample2.ts new file mode 100644 index 0000000..d64caa2 --- /dev/null +++ b/hardhat/test/confidentialCounter/sample2.ts @@ -0,0 +1,30 @@ +import { ethers } from "hardhat"; + +import { createInstance } from "../instance"; +import { getSigners, initSigners } from "../signers"; + +describe("EncryptedCounter2", function () { + before(async function () { + await initSigners(); // Initialize signers + this.signers = await getSigners(); + }); + + beforeEach(async function () { + const CounterFactory = await ethers.getContractFactory("EncryptedCounter2"); + this.counterContract = await CounterFactory.connect(this.signers.alice).deploy(); + await this.counterContract.waitForDeployment(); + this.contractAddress = await this.counterContract.getAddress(); + this.instances = await createInstance(); // Set up instances for testing + }); + + it("should increment by arbitrary encrypted amount", async function () { + // Create encrypted input for amount to increment by + const input = this.instances.createEncryptedInput(this.contractAddress, this.signers.alice.address); + input.add8(5); + const encryptedAmount = await input.encrypt(); + + // Call incrementBy with encrypted amount + const tx = await this.counterContract.incrementBy(encryptedAmount.handles[0], encryptedAmount.inputProof); + await tx.wait(); + }); +}); diff --git a/hardhat/test/confidentialCounter/sample3.ts b/hardhat/test/confidentialCounter/sample3.ts new file mode 100644 index 0000000..5793341 --- /dev/null +++ b/hardhat/test/confidentialCounter/sample3.ts @@ -0,0 +1,43 @@ +import { expect } from "chai"; +import { ethers } from "hardhat"; + +import { awaitAllDecryptionResults, initGateway } from "../asyncDecrypt"; +import { createInstance } from "../instance"; +import { getSigners, initSigners } from "../signers"; + +describe("EncryptedCounter3", function () { + before(async function () { + await initSigners(); // Initialize signers + this.signers = await getSigners(); + await initGateway(); // Initialize the gateway for decryption + }); + + beforeEach(async function () { + const CounterFactory = await ethers.getContractFactory("EncryptedCounter3"); + this.counterContract = await CounterFactory.connect(this.signers.alice).deploy(); + await this.counterContract.waitForDeployment(); + this.contractAddress = await this.counterContract.getAddress(); + this.instances = await createInstance(); // Set up instances for testing + }); + + it("should increment counter and decrypt the result", async function () { + // Create encrypted input for amount to increment by + const input = this.instances.createEncryptedInput(this.contractAddress, this.signers.alice.address); + input.add8(5); // Increment by 5 as an example + const encryptedAmount = await input.encrypt(); + + // Call incrementBy with encrypted amount + const tx = await this.counterContract.incrementBy(encryptedAmount.handles[0], encryptedAmount.inputProof); + await tx.wait(); + + const tx4 = await this.counterContract.connect(this.signers.carol).requestDecryptCounter(); + await tx4.wait(); + + // Wait for decryption to complete + await awaitAllDecryptionResults(); + + // Check decrypted value (should be 3: initial 0 + three increments) + const decryptedValue = await this.counterContract.getDecryptedCounter(); + expect(decryptedValue).to.equal(5); + }); +}); diff --git a/hardhat/test/confidentialCounter/sample4.ts b/hardhat/test/confidentialCounter/sample4.ts new file mode 100644 index 0000000..8944860 --- /dev/null +++ b/hardhat/test/confidentialCounter/sample4.ts @@ -0,0 +1,69 @@ +import { expect } from "chai"; +import { ethers } from "hardhat"; + +import { createInstance } from "../instance"; +import { reencryptEuint8 } from "../reencrypt"; +import { getSigners, initSigners } from "../signers"; + +describe("EncryptedCounter4", function () { + before(async function () { + await initSigners(); // Initialize signers + this.signers = await getSigners(); + }); + + beforeEach(async function () { + const CounterFactory = await ethers.getContractFactory("EncryptedCounter4"); + this.counterContract = await CounterFactory.connect(this.signers.alice).deploy(); + await this.counterContract.waitForDeployment(); + this.contractAddress = await this.counterContract.getAddress(); + this.instances = await createInstance(); + }); + + it("should allow reencryption and decryption of counter value", async function () { + const input = this.instances.createEncryptedInput(this.contractAddress, this.signers.alice.address); + input.add8(1); // Increment by 1 as an example + const encryptedAmount = await input.encrypt(); + + // Call incrementBy with encrypted amount + const tx = await this.counterContract.incrementBy(encryptedAmount.handles[0], encryptedAmount.inputProof); + await tx.wait(); + + // Get the encrypted counter value + const encryptedCounter = await this.counterContract.getCounter(); + + const decryptedValue = await reencryptEuint8( + this.signers.alice, + this.instances, + encryptedCounter, + this.contractAddress, + ); + + // Verify the decrypted value is 1 (since we incremented once) + expect(decryptedValue).to.equal(1); + }); + + it("should allow reencryption of counter value", async function () { + const input = this.instances.createEncryptedInput(this.contractAddress, this.signers.bob.address); + input.add8(1); // Increment by 1 as an example + const encryptedAmount = await input.encrypt(); + + // Call incrementBy with encrypted amount + const tx = await this.counterContract + .connect(this.signers.bob) + .incrementBy(encryptedAmount.handles[0], encryptedAmount.inputProof); + await tx.wait(); + + // Get the encrypted counter value + const encryptedCounter = await this.counterContract.connect(this.signers.bob).getCounter(); + + const decryptedValue = await reencryptEuint8( + this.signers.bob, + this.instances, + encryptedCounter, + this.contractAddress, + ); + + // Verify the decrypted value is 1 (since we incremented once) + expect(decryptedValue).to.equal(1); + }); +}); diff --git a/hardhat/test/confidentialERC20/ConfidentialERC20.fixture.ts b/hardhat/test/confidentialERC20/ConfidentialERC20.fixture.ts new file mode 100644 index 0000000..78881ff --- /dev/null +++ b/hardhat/test/confidentialERC20/ConfidentialERC20.fixture.ts @@ -0,0 +1,14 @@ +import { ethers } from "hardhat"; + +import type { MyConfidentialERC20 } from "../../types"; +import { getSigners } from "../signers"; + +export async function deployConfidentialERC20Fixture(): Promise { + const signers = await getSigners(); + + const contractFactory = await ethers.getContractFactory("MyConfidentialERC20"); + const contract = await contractFactory.connect(signers.alice).deploy("Naraggara", "NARA"); // City of Zama's battle + await contract.waitForDeployment(); + + return contract; +} diff --git a/hardhat/test/confidentialERC20/ConfidentialERC20.ts b/hardhat/test/confidentialERC20/ConfidentialERC20.ts new file mode 100644 index 0000000..f142172 --- /dev/null +++ b/hardhat/test/confidentialERC20/ConfidentialERC20.ts @@ -0,0 +1,217 @@ +import { expect } from "chai"; +import { network } from "hardhat"; + +import { awaitAllDecryptionResults, initGateway } from "../asyncDecrypt"; +import { createInstance } from "../instance"; +import { reencryptEuint64 } from "../reencrypt"; +import { getSigners, initSigners } from "../signers"; +import { debug } from "../utils"; +import { deployConfidentialERC20Fixture } from "./ConfidentialERC20.fixture"; + +describe("ConfidentialERC20", function () { + before(async function () { + await initSigners(); + this.signers = await getSigners(); + await initGateway(); + }); + + beforeEach(async function () { + const contract = await deployConfidentialERC20Fixture(); + this.contractAddress = await contract.getAddress(); + this.erc20 = contract; + this.fhevm = await createInstance(); + }); + + it("should mint the contract", async function () { + const transaction = await this.erc20.mint(this.signers.alice, 1000); + await transaction.wait(); + + // Reencrypt Alice's balance + const balanceHandleAlice = await this.erc20.balanceOf(this.signers.alice); + const balanceAlice = await reencryptEuint64( + this.signers.alice, + this.fhevm, + balanceHandleAlice, + this.contractAddress, + ); + + expect(balanceAlice).to.equal(1000); + + const totalSupply = await this.erc20.totalSupply(); + expect(totalSupply).to.equal(1000); + }); + + it("should transfer tokens between two users", async function () { + const transaction = await this.erc20.mint(this.signers.alice, 10000); + const t1 = await transaction.wait(); + expect(t1?.status).to.eq(1); + + const input = this.fhevm.createEncryptedInput(this.contractAddress, this.signers.alice.address); + input.add64(1337); + const encryptedTransferAmount = await input.encrypt(); + const tx = await this.erc20["transfer(address,bytes32,bytes)"]( + this.signers.bob, + encryptedTransferAmount.handles[0], + encryptedTransferAmount.inputProof, + ); + const t2 = await tx.wait(); + expect(t2?.status).to.eq(1); + + // Reencrypt Alice's balance + const balanceHandleAlice = await this.erc20.balanceOf(this.signers.alice); + const balanceAlice = await reencryptEuint64( + this.signers.alice, + this.fhevm, + balanceHandleAlice, + this.contractAddress, + ); + expect(balanceAlice).to.equal(10000 - 1337); + + // Reencrypt Bob's balance + const balanceHandleBob = await this.erc20.balanceOf(this.signers.bob); + const balanceBob = await reencryptEuint64(this.signers.bob, this.fhevm, balanceHandleBob, this.contractAddress); + expect(balanceBob).to.equal(1337); + + // on the other hand, Bob should be unable to read Alice's balance + await expect( + reencryptEuint64(this.signers.bob, this.fhevm, balanceHandleAlice, this.contractAddress), + ).to.be.rejectedWith("User is not authorized to reencrypt this handle!"); + + // and should be impossible to call reencrypt if contractAddress === userAddress + await expect( + reencryptEuint64(this.signers.alice, this.fhevm, balanceHandleAlice, this.signers.alice.address), + ).to.be.rejectedWith("userAddress should not be equal to contractAddress when requesting reencryption!"); + }); + + it("should not transfer tokens between two users", async function () { + const transaction = await this.erc20.mint(this.signers.alice, 1000); + await transaction.wait(); + + const input = this.fhevm.createEncryptedInput(this.contractAddress, this.signers.alice.address); + input.add64(1337); + const encryptedTransferAmount = await input.encrypt(); + const tx = await this.erc20["transfer(address,bytes32,bytes)"]( + this.signers.bob, + encryptedTransferAmount.handles[0], + encryptedTransferAmount.inputProof, + ); + await tx.wait(); + + const balanceHandleAlice = await this.erc20.balanceOf(this.signers.alice); + const balanceAlice = await reencryptEuint64( + this.signers.alice, + this.fhevm, + balanceHandleAlice, + this.contractAddress, + ); + expect(balanceAlice).to.equal(1000); + + // Reencrypt Bob's balance + const balanceHandleBob = await this.erc20.balanceOf(this.signers.bob); + const balanceBob = await reencryptEuint64(this.signers.bob, this.fhevm, balanceHandleBob, this.contractAddress); + expect(balanceBob).to.equal(0); + }); + + it("should be able to transferFrom only if allowance is sufficient", async function () { + const transaction = await this.erc20.mint(this.signers.alice, 10000); + await transaction.wait(); + + const inputAlice = this.fhevm.createEncryptedInput(this.contractAddress, this.signers.alice.address); + inputAlice.add64(1337); + const encryptedAllowanceAmount = await inputAlice.encrypt(); + const tx = await this.erc20["approve(address,bytes32,bytes)"]( + this.signers.bob, + encryptedAllowanceAmount.handles[0], + encryptedAllowanceAmount.inputProof, + ); + await tx.wait(); + + const bobErc20 = this.erc20.connect(this.signers.bob); + const inputBob1 = this.fhevm.createEncryptedInput(this.contractAddress, this.signers.bob.address); + inputBob1.add64(1338); // above allowance so next tx should actually not send any token + const encryptedTransferAmount = await inputBob1.encrypt(); + const tx2 = await bobErc20["transferFrom(address,address,bytes32,bytes)"]( + this.signers.alice, + this.signers.bob, + encryptedTransferAmount.handles[0], + encryptedTransferAmount.inputProof, + ); + await tx2.wait(); + + // Decrypt Alice's balance + const balanceHandleAlice = await this.erc20.balanceOf(this.signers.alice); + const balanceAlice = await reencryptEuint64( + this.signers.alice, + this.fhevm, + balanceHandleAlice, + this.contractAddress, + ); + expect(balanceAlice).to.equal(10000); // check that transfer did not happen, as expected + + // Decrypt Bob's balance + const balanceHandleBob = await this.erc20.balanceOf(this.signers.bob); + const balanceBob = await reencryptEuint64(this.signers.bob, this.fhevm, balanceHandleBob, this.contractAddress); + expect(balanceBob).to.equal(0); // check that transfer did not happen, as expected + + const inputBob2 = this.fhevm.createEncryptedInput(this.contractAddress, this.signers.bob.address); + inputBob2.add64(1337); // below allowance so next tx should send token + const encryptedTransferAmount2 = await inputBob2.encrypt(); + const tx3 = await bobErc20["transferFrom(address,address,bytes32,bytes)"]( + this.signers.alice, + this.signers.bob, + encryptedTransferAmount2.handles[0], + encryptedTransferAmount2.inputProof, + ); + await tx3.wait(); + + // Decrypt Alice's balance + const balanceHandleAlice2 = await this.erc20.balanceOf(this.signers.alice); + const balanceAlice2 = await reencryptEuint64( + this.signers.alice, + this.fhevm, + balanceHandleAlice2, + this.contractAddress, + ); + expect(balanceAlice2).to.equal(10000 - 1337); // check that transfer did happen this time + + // Decrypt Bob's balance + const balanceHandleBob2 = await this.erc20.balanceOf(this.signers.bob); + const balanceBob2 = await reencryptEuint64(this.signers.bob, this.fhevm, balanceHandleBob2, this.contractAddress); + expect(balanceBob2).to.equal(1337); // check that transfer did happen this time + }); + + it("should decrypt the SECRET value", async function () { + const tx2 = await this.erc20.requestSecret(); + await tx2.wait(); + await awaitAllDecryptionResults(); + const y = await this.erc20.revealedSecret(); + expect(y).to.equal(42n); + }); + + it("DEBUG - using debug.decrypt64 for debugging transfer", async function () { + if (network.name === "hardhat") { + // using the debug.decryptXX functions is possible only in mocked mode + + const transaction = await this.erc20.mint(this.signers.alice, 1000); + await transaction.wait(); + const input = this.fhevm.createEncryptedInput(this.contractAddress, this.signers.alice.address); + input.add64(1337); + const encryptedTransferAmount = await input.encrypt(); + const tx = await this.erc20["transfer(address,bytes32,bytes)"]( + this.signers.bob, + encryptedTransferAmount.handles[0], + encryptedTransferAmount.inputProof, + ); + await tx.wait(); + + const balanceHandleAlice = await this.erc20.balanceOf(this.signers.alice); + const balanceAlice = await debug.decrypt64(balanceHandleAlice); + expect(balanceAlice).to.equal(1000); + + // Reencrypt Bob's balance + const balanceHandleBob = await this.erc20.balanceOf(this.signers.bob); + const balanceBob = await debug.decrypt64(balanceHandleBob); + expect(balanceBob).to.equal(0); + } + }); +}); diff --git a/hardhat/test/constants.ts b/hardhat/test/constants.ts new file mode 100644 index 0000000..7c9d80e --- /dev/null +++ b/hardhat/test/constants.ts @@ -0,0 +1,10 @@ +export const TFHEEXECUTOR_ADDRESS = "0x687408ab54661ba0b4aef3a44156c616c6955e07"; +export const ACL_ADDRESS = "0xfee8407e2f5e3ee68ad77cae98c434e637f516e5"; +export const FHEPAYMENT_ADDRESS = "0xfb03be574d14c256d56f09a198b586bdfc0a9de2"; +export const KMSVERIFIER_ADDRESS = "0x9d6891a6240d6130c54ae243d8005063d05fe14b"; +export const INPUTVERIFIER_ADDRESS = "0x3a2DA6f1daE9eF988B48d9CF27523FA31a8eBE50"; +export const GATEWAYCONTRACT_ADDRESS = "0x33347831500f1e73f0cccbb95c9f86b94d7b1123"; +export const PRIVATE_KEY_KMS_SIGNER = "388b7680e4e1afa06efbfd45cdd1fe39f3c6af381df6555a19661f283b97de91"; +export const PRIVATE_KEY_COPROCESSOR_ACCOUNT = "7ec8ada6642fc4ccfb7729bc29c17cf8d21b61abd5642d1db992c0b8672ab901"; +export const GATEWAY_URL = "https://gateway.sepolia.zama.ai/"; +export const ACCOUNT_NAMES = ["alice", "bob", "carol", "dave", "eve", "fred", "greg", "hugo", "ian", "jane"]; diff --git a/hardhat/test/coprocessorUtils.ts b/hardhat/test/coprocessorUtils.ts new file mode 100644 index 0000000..e7e1fe7 --- /dev/null +++ b/hardhat/test/coprocessorUtils.ts @@ -0,0 +1,901 @@ +import { log2 } from "extra-bigint"; +import { ethers } from "hardhat"; +import hre from "hardhat"; +import { Database } from "sqlite3"; + +import { TFHEEXECUTOR_ADDRESS } from "./constants"; +import operatorPrices from "./operatorPrices.json"; + +const executorAddress = TFHEEXECUTOR_ADDRESS; + +let firstBlockListening = 0; +let lastBlockSnapshot = 0; +let lastCounterRand = 0; +let counterRand = 0; + +//const db = new Database("./sql.db"); // on-disk db for debugging +const db = new Database(":memory:"); + +export function insertSQL(handle: string, clearText: bigint, replace: boolean = false) { + if (replace) { + // this is useful if using snapshots while sampling different random numbers on each revert + db.run("INSERT OR REPLACE INTO ciphertexts (handle, clearText) VALUES (?, ?)", [handle, clearText.toString()]); + } else { + db.run("INSERT OR IGNORE INTO ciphertexts (handle, clearText) VALUES (?, ?)", [handle, clearText.toString()]); + } +} + +// Decrypt any handle, bypassing ACL +// WARNING : only for testing or internal use +export const getClearText = async (handle: bigint): Promise => { + const handleStr = "0x" + handle.toString(16).padStart(64, "0"); + + return new Promise((resolve, reject) => { + let attempts = 0; + const maxRetries = 100; + + function executeQuery() { + db.get("SELECT clearText FROM ciphertexts WHERE handle = ?", [handleStr], (err, row) => { + if (err) { + reject(new Error(`Error querying database: ${err.message}`)); + } else if (row) { + resolve(row.clearText); + } else if (attempts < maxRetries) { + attempts++; + executeQuery(); + } else { + reject(new Error("No record found after maximum retries")); + } + }); + } + + executeQuery(); + }); +}; + +db.serialize(() => db.run("CREATE TABLE IF NOT EXISTS ciphertexts (handle BINARY PRIMARY KEY,clearText TEXT)")); + +interface FHEVMEvent { + eventName: string; + args: object; +} + +const NumBits = { + 0: 1n, //ebool + 1: 4n, //euint4 + 2: 8n, //euint8 + 3: 16n, //euint16 + 4: 32n, //euint32 + 5: 64n, //euint64 + 6: 128n, //euint128 + 7: 160n, //eaddress + 8: 256n, //euint256 + 9: 512n, //ebytes64 + 10: 1024n, //ebytes128 + 11: 2048n, //ebytes256 +}; + +export function numberToEvenHexString(num: number) { + if (typeof num !== "number" || num < 0) { + throw new Error("Input should be a non-negative number."); + } + let hexString = num.toString(16); + if (hexString.length % 2 !== 0) { + hexString = "0" + hexString; + } + return hexString; +} + +function getRandomBigInt(numBits: number): bigint { + if (numBits <= 0) { + throw new Error("Number of bits must be greater than 0"); + } + const numBytes = Math.ceil(numBits / 8); + const randomBytes = new Uint8Array(numBytes); + crypto.getRandomValues(randomBytes); + let randomBigInt = BigInt(0); + for (let i = 0; i < numBytes; i++) { + randomBigInt = (randomBigInt << BigInt(8)) | BigInt(randomBytes[i]); + } + const mask = (BigInt(1) << BigInt(numBits)) - BigInt(1); + randomBigInt = randomBigInt & mask; + return randomBigInt; +} + +function bitwiseNotUintBits(value: bigint, numBits: number) { + if (typeof value !== "bigint") { + throw new TypeError("The input value must be a BigInt."); + } + if (typeof numBits !== "number" || numBits <= 0) { + throw new TypeError("The numBits parameter must be a positive integer."); + } + // Create the mask with numBits bits set to 1 + const BIT_MASK = (BigInt(1) << BigInt(numBits)) - BigInt(1); + return ~value & BIT_MASK; +} + +export const awaitCoprocessor = async (): Promise => { + await processAllPastTFHEExecutorEvents(); +}; + +const abi = [ + "event FheAdd(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheSub(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheMul(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheDiv(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheRem(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheBitAnd(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheBitOr(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheBitXor(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheShl(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheShr(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheRotl(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheRotr(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheEq(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheEqBytes(uint256 lhs, bytes rhs, bytes1 scalarByte, uint256 result)", + "event FheNe(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheNeBytes(uint256 lhs, bytes rhs, bytes1 scalarByte, uint256 result)", + "event FheGe(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheGt(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheLe(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheLt(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheMin(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheMax(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", + "event FheNeg(uint256 ct, uint256 result)", + "event FheNot(uint256 ct, uint256 result)", + "event VerifyCiphertext(bytes32 inputHandle,address userAddress,bytes inputProof,bytes1 inputType,uint256 result)", + "event Cast(uint256 ct, bytes1 toType, uint256 result)", + "event TrivialEncrypt(uint256 pt, bytes1 toType, uint256 result)", + "event TrivialEncryptBytes(bytes pt, bytes1 toType, uint256 result)", + "event FheIfThenElse(uint256 control, uint256 ifTrue, uint256 ifFalse, uint256 result)", + "event FheRand(bytes1 randType, uint256 result)", + "event FheRandBounded(uint256 upperBound, bytes1 randType, uint256 result)", +]; + +async function processAllPastTFHEExecutorEvents() { + const provider = ethers.provider; + const latestBlockNumber = await provider.getBlockNumber(); + + if (hre.__SOLIDITY_COVERAGE_RUNNING !== true) { + // evm_snapshot is not supported in coverage mode + [lastBlockSnapshot, lastCounterRand] = await provider.send("get_lastBlockSnapshot"); + if (lastBlockSnapshot < firstBlockListening) { + firstBlockListening = lastBlockSnapshot + 1; + counterRand = Number(lastCounterRand); + } + } + + const contract = new ethers.Contract(executorAddress, abi, provider); + + // Fetch all events emitted by the contract + const filter = { + address: executorAddress, + fromBlock: firstBlockListening, + toBlock: latestBlockNumber, + }; + + const logs = await provider.getLogs(filter); + + const events = logs + .map((log) => { + try { + const parsedLog = contract.interface.parseLog(log); + return { + eventName: parsedLog.name, + args: parsedLog.args, + }; + } catch (e) { + // If the log cannot be parsed, skip it + return null; + } + }) + .filter((event) => event !== null); + + firstBlockListening = latestBlockNumber + 1; + if (hre.__SOLIDITY_COVERAGE_RUNNING !== true) { + // evm_snapshot is not supported in coverage mode + await provider.send("set_lastBlockSnapshot", [firstBlockListening]); + } + events.map(async (event) => await insertHandleFromEvent(event)); +} + +async function insertHandleFromEvent(event: FHEVMEvent) { + let handle; + let clearText; + let clearLHS; + let clearRHS; + let resultType; + let shift; + + switch (event.eventName) { + case "TrivialEncrypt": + clearText = event.args[0]; + handle = ethers.toBeHex(event.args[2], 32); + insertSQL(handle, clearText); + break; + + case "TrivialEncryptBytes": + clearText = event.args[0]; + handle = ethers.toBeHex(event.args[2], 32); + insertSQL(handle, clearText); + break; + + case "FheAdd": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) + event.args[1]; + clearText = clearText % 2n ** NumBits[resultType]; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) + BigInt(clearRHS); + clearText = clearText % 2n ** NumBits[resultType]; + } + insertSQL(ethers.toBeHex(handle, 32), clearText); + break; + + case "FheSub": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) - event.args[1]; + if (clearText < 0n) clearText = clearText + 2n ** NumBits[resultType]; + clearText = clearText % 2n ** NumBits[resultType]; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) - BigInt(clearRHS); + if (clearText < 0n) clearText = clearText + 2n ** NumBits[resultType]; + clearText = clearText % 2n ** NumBits[resultType]; + } + insertSQL(handle, clearText); + break; + + case "FheMul": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) * event.args[1]; + clearText = clearText % 2n ** NumBits[resultType]; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) * BigInt(clearRHS); + clearText = clearText % 2n ** NumBits[resultType]; + } + insertSQL(handle, clearText); + break; + + case "FheDiv": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) / event.args[1]; + } else { + throw new Error("Non-scalar div not implemented yet"); + } + insertSQL(handle, clearText); + break; + + case "FheRem": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) % event.args[1]; + } else { + throw new Error("Non-scalar rem not implemented yet"); + } + insertSQL(handle, clearText); + break; + + case "FheBitAnd": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) & event.args[1]; + clearText = clearText % 2n ** NumBits[resultType]; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) & BigInt(clearRHS); + clearText = clearText % 2n ** NumBits[resultType]; + } + insertSQL(handle, clearText); + break; + + case "FheBitOr": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) | event.args[1]; + clearText = clearText % 2n ** NumBits[resultType]; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) | BigInt(clearRHS); + clearText = clearText % 2n ** NumBits[resultType]; + } + insertSQL(handle, clearText); + break; + + case "FheBitXor": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) ^ event.args[1]; + clearText = clearText % 2n ** NumBits[resultType]; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) ^ BigInt(clearRHS); + clearText = clearText % 2n ** NumBits[resultType]; + } + insertSQL(handle, clearText); + break; + + case "FheShl": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) << event.args[1] % NumBits[resultType]; + clearText = clearText % 2n ** NumBits[resultType]; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) << BigInt(clearRHS) % NumBits[resultType]; + clearText = clearText % 2n ** NumBits[resultType]; + } + insertSQL(handle, clearText); + break; + + case "FheShr": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) >> event.args[1] % NumBits[resultType]; + clearText = clearText % 2n ** NumBits[resultType]; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) >> BigInt(clearRHS) % NumBits[resultType]; + clearText = clearText % 2n ** NumBits[resultType]; + } + insertSQL(handle, clearText); + break; + + case "FheRotl": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + shift = event.args[1] % NumBits[resultType]; + clearText = (BigInt(clearLHS) << shift) | (BigInt(clearLHS) >> (NumBits[resultType] - shift)); + clearText = clearText % 2n ** NumBits[resultType]; + } else { + clearRHS = await getClearText(event.args[1]); + shift = BigInt(clearRHS) % NumBits[resultType]; + clearText = (BigInt(clearLHS) << shift) | (BigInt(clearLHS) >> (NumBits[resultType] - shift)); + clearText = clearText % 2n ** NumBits[resultType]; + } + insertSQL(handle, clearText); + break; + + case "FheRotr": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + shift = event.args[1] % NumBits[resultType]; + clearText = (BigInt(clearLHS) >> shift) | (BigInt(clearLHS) << (NumBits[resultType] - shift)); + clearText = clearText % 2n ** NumBits[resultType]; + } else { + clearRHS = await getClearText(event.args[1]); + shift = BigInt(clearRHS) % NumBits[resultType]; + clearText = (BigInt(clearLHS) >> shift) | (BigInt(clearLHS) << (NumBits[resultType] - shift)); + clearText = clearText % 2n ** NumBits[resultType]; + } + insertSQL(handle, clearText); + break; + + case "FheEq": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) === event.args[1] ? 1n : 0n; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) === BigInt(clearRHS) ? 1n : 0n; + } + insertSQL(handle, clearText); + break; + + case "FheEqBytes": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) === BigInt(event.args[1]) ? 1n : 0n; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) === BigInt(clearRHS) ? 1n : 0n; + } + insertSQL(handle, clearText); + break; + + case "FheNe": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) !== event.args[1] ? 1n : 0n; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) !== BigInt(clearRHS) ? 1n : 0n; + } + insertSQL(handle, clearText); + break; + + case "FheNeBytes": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) !== BigInt(event.args[1]) ? 1n : 0n; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) !== BigInt(clearRHS) ? 1n : 0n; + } + insertSQL(handle, clearText); + break; + + case "FheGe": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) >= event.args[1] ? 1n : 0n; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) >= BigInt(clearRHS) ? 1n : 0n; + } + insertSQL(handle, clearText); + break; + + case "FheGt": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) > event.args[1] ? 1n : 0n; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) > BigInt(clearRHS) ? 1n : 0n; + } + insertSQL(handle, clearText); + break; + + case "FheLe": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) <= event.args[1] ? 1n : 0n; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) <= BigInt(clearRHS) ? 1n : 0n; + } + insertSQL(handle, clearText); + break; + + case "FheLt": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) < event.args[1] ? 1n : 0n; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) < BigInt(clearRHS) ? 1n : 0n; + } + insertSQL(handle, clearText); + break; + + case "FheMax": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) > event.args[1] ? clearLHS : event.args[1]; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) > BigInt(clearRHS) ? clearLHS : clearRHS; + } + insertSQL(handle, clearText); + break; + + case "FheMin": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearLHS = await getClearText(event.args[0]); + if (event.args[2] === "0x01") { + clearText = BigInt(clearLHS) < event.args[1] ? clearLHS : event.args[1]; + } else { + clearRHS = await getClearText(event.args[1]); + clearText = BigInt(clearLHS) < BigInt(clearRHS) ? clearLHS : clearRHS; + } + insertSQL(handle, clearText); + break; + + case "Cast": + resultType = parseInt(event.args[1]); + handle = ethers.toBeHex(event.args[2], 32); + clearText = BigInt(await getClearText(event.args[0])) % 2n ** NumBits[resultType]; + insertSQL(handle, clearText); + break; + + case "FheNot": + handle = ethers.toBeHex(event.args[1], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearText = BigInt(await getClearText(event.args[0])); + clearText = bitwiseNotUintBits(clearText, Number(NumBits[resultType])); + insertSQL(handle, clearText); + break; + + case "FheNeg": + handle = ethers.toBeHex(event.args[1], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + clearText = BigInt(await getClearText(event.args[0])); + clearText = bitwiseNotUintBits(clearText, Number(NumBits[resultType])); + clearText = (clearText + 1n) % 2n ** NumBits[resultType]; + insertSQL(handle, clearText); + break; + + case "VerifyCiphertext": + handle = event.args[0]; + try { + await getClearText(BigInt(handle)); + } catch { + throw Error("User input was not found in DB"); + } + break; + + case "FheIfThenElse": + handle = ethers.toBeHex(event.args[3], 32); + resultType = parseInt(handle.slice(-4, -2), 16); + handle = ethers.toBeHex(event.args[3], 32); + const clearControl = BigInt(await getClearText(event.args[0])); + const clearIfTrue = BigInt(await getClearText(event.args[1])); + const clearIfFalse = BigInt(await getClearText(event.args[2])); + if (clearControl === 1n) { + clearText = clearIfTrue; + } else { + clearText = clearIfFalse; + } + insertSQL(handle, clearText); + break; + + case "FheRand": + resultType = parseInt(event.args[0], 16); + handle = ethers.toBeHex(event.args[1], 32); + clearText = getRandomBigInt(Number(NumBits[resultType])); + insertSQL(handle, clearText, true); + counterRand++; + break; + + case "FheRandBounded": + resultType = parseInt(event.args[1], 16); + handle = ethers.toBeHex(event.args[2], 32); + clearText = getRandomBigInt(Number(log2(BigInt(event.args[0])))); + insertSQL(handle, clearText, true); + counterRand++; + break; + } +} + +export function getFHEGasFromTxReceipt(receipt: ethers.TransactionReceipt): number { + if (hre.network.name !== "hardhat") { + throw Error("FHEGas tracking is currently implemented only in mocked mode"); + } + if (receipt.status === 0) { + throw new Error("Transaction reverted"); + } + const contract = new ethers.Contract(executorAddress, abi, ethers.provider); + const relevantLogs = receipt.logs.filter((log: ethers.Log) => { + if (log.address.toLowerCase() !== executorAddress.toLowerCase()) { + return false; + } + try { + const parsedLog = contract.interface.parseLog({ + topics: log.topics, + data: log.data, + }); + return abi.some((item) => item.startsWith(`event ${parsedLog.name}`) && parsedLog.name !== "VerifyCiphertext"); + } catch { + return false; + } + }); + const FHELogs = relevantLogs.map((log: ethers.Log) => { + const parsedLog = contract.interface.parseLog({ + topics: log.topics, + data: log.data, + }); + return { + name: parsedLog.name, + args: parsedLog.args, + }; + }); + let FHEGasConsumed = 0; + for (const event of FHELogs) { + let type; + let handle; + switch (event.name) { + case "TrivialEncrypt": + type = parseInt(event.args[1], 16); + FHEGasConsumed += operatorPrices["trivialEncrypt"].types[type]; + break; + + case "TrivialEncryptBytes": + type = parseInt(event.args[1], 16); + FHEGasConsumed += operatorPrices["trivialEncrypt"].types[type]; + break; + + case "FheAdd": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorPrices["fheAdd"].scalar[type]; + } else { + FHEGasConsumed += operatorPrices["fheAdd"].nonScalar[type]; + } + break; + + case "FheSub": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorPrices["fheSub"].scalar[type]; + } else { + FHEGasConsumed += operatorPrices["fheSub"].nonScalar[type]; + } + break; + + case "FheMul": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorPrices["fheMul"].scalar[type]; + } else { + FHEGasConsumed += operatorPrices["fheMul"].nonScalar[type]; + } + break; + + case "FheDiv": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorPrices["fheDiv"].scalar[type]; + } else { + throw new Error("Non-scalar div not implemented yet"); + } + break; + + case "FheRem": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorPrices["fheRem"].scalar[type]; + } else { + throw new Error("Non-scalar rem not implemented yet"); + } + break; + + case "FheBitAnd": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorPrices["fheBitAnd"].scalar[type]; + } else { + FHEGasConsumed += operatorPrices["fheBitAnd"].nonScalar[type]; + } + break; + + case "FheBitOr": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorPrices["fheBitOr"].scalar[type]; + } else { + FHEGasConsumed += operatorPrices["fheBitOr"].nonScalar[type]; + } + break; + + case "FheBitXor": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorPrices["fheBitXor"].scalar[type]; + } else { + FHEGasConsumed += operatorPrices["fheBitXor"].nonScalar[type]; + } + break; + + case "FheShl": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorPrices["fheBitShl"].scalar[type]; + } else { + FHEGasConsumed += operatorPrices["fheBitShl"].nonScalar[type]; + } + break; + + case "FheShr": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorPrices["fheBitShr"].scalar[type]; + } else { + FHEGasConsumed += operatorPrices["fheBitShr"].nonScalar[type]; + } + break; + + case "FheRotl": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorPrices["fheRotl"].scalar[type]; + } else { + FHEGasConsumed += operatorPrices["fheRotl"].nonScalar[type]; + } + break; + + case "FheRotr": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorPrices["fheRotr"].scalar[type]; + } else { + FHEGasConsumed += operatorPrices["fheRotr"].nonScalar[type]; + } + break; + + case "FheEq": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorPrices["fheEq"].scalar[type]; + } else { + FHEGasConsumed += operatorPrices["fheEq"].nonScalar[type]; + } + break; + + case "FheEqBytes": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorPrices["fheEq"].scalar[type]; + } else { + FHEGasConsumed += operatorPrices["fheEq"].nonScalar[type]; + } + + case "FheNe": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorPrices["fheNe"].scalar[type]; + } else { + FHEGasConsumed += operatorPrices["fheNe"].nonScalar[type]; + } + break; + + case "FheNeBytes": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorPrices["fheNe"].scalar[type]; + } else { + FHEGasConsumed += operatorPrices["fheNe"].nonScalar[type]; + } + break; + + case "FheGe": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorPrices["fheGe"].scalar[type]; + } else { + FHEGasConsumed += operatorPrices["fheGe"].nonScalar[type]; + } + break; + + case "FheGt": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorPrices["fheGt"].scalar[type]; + } else { + FHEGasConsumed += operatorPrices["fheGt"].nonScalar[type]; + } + break; + + case "FheLe": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorPrices["fheLe"].scalar[type]; + } else { + FHEGasConsumed += operatorPrices["fheLe"].nonScalar[type]; + } + break; + + case "FheLt": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorPrices["fheLt"].scalar[type]; + } else { + FHEGasConsumed += operatorPrices["fheLt"].nonScalar[type]; + } + break; + + case "FheMax": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorPrices["fheMax"].scalar[type]; + } else { + FHEGasConsumed += operatorPrices["fheMax"].nonScalar[type]; + } + break; + + case "FheMin": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + if (event.args[2] === "0x01") { + FHEGasConsumed += operatorPrices["fheMin"].scalar[type]; + } else { + FHEGasConsumed += operatorPrices["fheMin"].nonScalar[type]; + } + break; + + case "Cast": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + FHEGasConsumed += operatorPrices["cast"].types[type]; + break; + + case "FheNot": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + FHEGasConsumed += operatorPrices["fheNot"].types[type]; + break; + + case "FheNeg": + handle = ethers.toBeHex(event.args[0], 32); + type = parseInt(handle.slice(-4, -2), 16); + FHEGasConsumed += operatorPrices["fheNeg"].types[type]; + break; + + case "FheIfThenElse": + handle = ethers.toBeHex(event.args[3], 32); + type = parseInt(handle.slice(-4, -2), 16); + FHEGasConsumed += operatorPrices["ifThenElse"].types[type]; + break; + + case "FheRand": + type = parseInt(event.args[0], 16); + FHEGasConsumed += operatorPrices["fheRand"].types[type]; + break; + + case "FheRandBounded": + type = parseInt(event.args[1], 16); + FHEGasConsumed += operatorPrices["fheRandBounded"].types[type]; + break; + } + } + return FHEGasConsumed; +} diff --git a/hardhat/test/decIdentity/diploma.ts b/hardhat/test/decIdentity/diploma.ts new file mode 100644 index 0000000..ec087d8 --- /dev/null +++ b/hardhat/test/decIdentity/diploma.ts @@ -0,0 +1,346 @@ +import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers"; +import { toBufferBE } from "bigint-buffer"; +import { expect } from "chai"; +import type { FhevmInstance } from "fhevmjs"; + +import type { Diploma, EmployerClaim, IdMapping, PassportID } from "../../types"; +import { createInstance } from "../instance"; +import { reencryptEbool, reencryptEbytes64, reencryptEuint8, reencryptEuint16 } from "../reencrypt"; +import { getSigners, initSigners } from "../signers"; +import { bigIntToBytes64 } from "../utils"; +import { deployEmployerClaimFixture } from "./fixture/EmployerClaim.fixture"; + +/** + * Utility function to convert a bigint value to a 256-bit byte array + * @param value - The bigint value to convert + * @returns A Uint8Array representing the 256-bit byte array + */ +export const bigIntToBytes256 = (value: bigint) => { + return new Uint8Array(toBufferBE(value, 256)); +}; + +/** + * Integration test suite for PassportID and EmployerClaim contracts + * Tests the core functionality of diploma registration, verification and claim generation + */ +describe("Diploma", function () { + let passportID: PassportID; + let employerClaim: EmployerClaim; + let diplomaID: Diploma; + let idMapping: IdMapping; + + /** + * Initialize test signers before running any tests + * Sets up alice and other signers that will be used across test cases + */ + before(async function () { + await initSigners(); + this.signers = await getSigners(); + }); + + /** + * Deploy fresh contract instances before each test + * Sets up clean state with new PassportID, EmployerClaim, Diploma and IdMapping contracts + */ + beforeEach(async function () { + const deployment = await deployEmployerClaimFixture(); + employerClaim = deployment.employerClaim; + passportID = deployment.passportID; + diplomaID = deployment.diploma; + idMapping = deployment.idMapping; + + this.employerClaimAddress = await employerClaim.getAddress(); + this.diplomaAddress = await diplomaID.getAddress(); + this.passportIDAddress = await passportID.getAddress(); + this.idMappingAddress = await idMapping.getAddress(); + + this.instances = await createInstance(); + }); + + /** + * Helper function to register a diploma for a user + */ + async function registerDiploma( + userId: bigint, + instance: FhevmInstance, + diplomaAddress: string, + signer: HardhatEthersSigner, + university = bigIntToBytes64(8n), + degree = 8, + grade = bigIntToBytes64(8n), + ) { + const input = instance.createEncryptedInput(diplomaAddress, signer.address); + const encryptedData = await input.addBytes64(university).add16(degree).addBytes64(grade).encrypt(); + + await diplomaID + .connect(signer) + .registerDiploma( + userId, + encryptedData.handles[0], + encryptedData.handles[1], + encryptedData.handles[2], + encryptedData.inputProof, + ); + } + + // /** + // * Helper function to setup reencryption + // */ + // async function setupReencryption(instance: FhevmInstance, signer: HardhatEthersSigner, contractAddress: string) { + // const { publicKey, privateKey } = instance.generateKeypair(); + // const eip712 = instance.createEIP712(publicKey, contractAddress); + // const signature = await signer.signTypedData(eip712.domain, { Reencrypt: eip712.types.Reencrypt }, eip712.message); + + // return { publicKey, privateKey, signature: signature.replace("0x", "") }; + // } + + /** + * Helper function to register identity + */ + async function registerIdentity( + userId: bigint, + instance: FhevmInstance, + passportAddress: string, + signer: HardhatEthersSigner, + biodata = bigIntToBytes64(8n), + firstname = bigIntToBytes64(8n), + lastname = bigIntToBytes64(8n), + birthdate = 946681200n, // Sat Jan 01 2000 - 24 years old + ) { + const input = instance.createEncryptedInput(passportAddress, signer.address); + const encryptedData = await input + .addBytes64(biodata) + .addBytes64(firstname) + .addBytes64(lastname) + .add64(birthdate) + .encrypt(); + + await passportID + .connect(signer) + .registerIdentity( + userId, + encryptedData.handles[0], + encryptedData.handles[1], + encryptedData.handles[2], + encryptedData.handles[3], + encryptedData.inputProof, + ); + } + + it("should register an identity successfully", async function () { + await idMapping.connect(this.signers.alice).generateId(); + const userId = await idMapping.getId(this.signers.alice); + + await registerDiploma(userId, this.instances, this.diplomaAddress, this.signers.alice); + + expect(await diplomaID.registered(userId)); + }); + + it("should prevent duplicate registration for the same user", async function () { + await idMapping.connect(this.signers.alice).generateId(); + const userId = await idMapping.getId(this.signers.alice); + + await registerDiploma(userId, this.instances, this.diplomaAddress, this.signers.alice); + + await expect( + registerDiploma(userId, this.instances, this.diplomaAddress, this.signers.alice), + ).to.be.revertedWithCustomError(diplomaID, "DiplomaAlreadyRegistered"); + }); + + it("should retrieve the registered identity", async function () { + await idMapping.connect(this.signers.alice).generateId(); + const userId = await idMapping.getId(this.signers.alice); + + await registerDiploma(userId, this.instances, this.diplomaAddress, this.signers.alice); + + const universityHandleAlice = await diplomaID.getMyUniversity(userId); + + const reencryptedUniversity = await reencryptEbytes64( + this.signers.alice, + this.instances, + universityHandleAlice, + this.diplomaAddress, + ); + + expect(reencryptedUniversity).to.equal(8); + }); + + it("should generate an degree claim", async function () { + await idMapping.connect(this.signers.alice).generateId(); + const userId = await idMapping.getId(this.signers.alice); + + await registerDiploma(userId, this.instances, this.diplomaAddress, this.signers.alice); + + const tx = await diplomaID + .connect(this.signers.alice) + .generateClaim(this.employerClaimAddress, "generateDegreeClaim(uint256)"); + + await expect(tx).to.emit(employerClaim, "DegreeClaimGenerated"); + + const latestClaimUserId = await employerClaim.lastClaimId(); + const degreeClaim = await employerClaim.getDegreeClaim(latestClaimUserId); + + const reencryptedDegreeClaim = await reencryptEbool( + this.signers.alice, + this.instances, + degreeClaim, + this.diplomaAddress, + ); + + expect(reencryptedDegreeClaim).to.equal(0); + }); + + it("should generate both degree and adult claims", async function () { + await idMapping.connect(this.signers.alice).generateId(); + const userId = await idMapping.getId(this.signers.alice); + + await registerDiploma( + userId, + this.instances, + this.diplomaAddress, + this.signers.alice, + bigIntToBytes64(8n), + 3, // Computer Science (B.Sc) + bigIntToBytes64(8n), + ); + + const degreeTx = await diplomaID + .connect(this.signers.alice) + .generateClaim(this.employerClaimAddress, "generateDegreeClaim(uint256)"); + + await expect(degreeTx).to.emit(employerClaim, "DegreeClaimGenerated"); + + const latestDegreeClaimUserId = await employerClaim.lastClaimId(); + const degreeClaim = await employerClaim.getDegreeClaim(latestDegreeClaimUserId); + + await registerIdentity(userId, this.instances, this.passportIDAddress, this.signers.alice); + + const adultTx = await passportID + .connect(this.signers.alice) + .generateClaim(this.employerClaimAddress, "generateAdultClaim(uint256)"); + + await expect(adultTx).to.emit(employerClaim, "AdultClaimGenerated"); + + const latestAdultClaimUserId = await employerClaim.lastClaimId(); + const adultClaim = await employerClaim.getAdultClaim(latestAdultClaimUserId); + + const reencryptedDegreeClaim = await reencryptEbool( + this.signers.alice, + this.instances, + degreeClaim, + this.diplomaAddress, + ); + + const reencryptedAdultClaim = await reencryptEbool( + this.signers.alice, + this.instances, + adultClaim, + this.diplomaAddress, + ); + + expect(reencryptedDegreeClaim).to.equal(1); + expect(reencryptedAdultClaim).to.equal(1); + + await employerClaim.verifyClaims(userId, latestAdultClaimUserId, latestDegreeClaimUserId); + const verifyResult = await employerClaim.getVerifyClaim(userId); + + const reencryptedVerifyResult = await reencryptEbool( + this.signers.alice, + this.instances, + verifyResult, + this.diplomaAddress, + ); + + expect(reencryptedVerifyResult).to.equal(1); + }); + + it("should not allow generating claims without a registered ID", async function () { + // Try to generate degree claim without registering ID first + await expect( + diplomaID.connect(this.signers.alice).generateClaim(this.employerClaimAddress, "generateDegreeClaim(uint256)"), + ).to.be.revertedWithCustomError(idMapping, "NoIdGenerated"); + + // Try to generate adult claim without registering ID first + await expect( + passportID.connect(this.signers.alice).generateClaim(this.employerClaimAddress, "generateAdultClaim(uint256)"), + ).to.be.revertedWithCustomError(idMapping, "NoIdGenerated"); + }); + + it("should not allow generating claims with unregistered diploma/identity", async function () { + // Generate ID but don't register diploma/identity + await idMapping.connect(this.signers.alice).generateId(); + const userId = await idMapping.getId(this.signers.alice); + + // Try to generate degree claim without registering diploma + await expect( + diplomaID.connect(this.signers.alice).generateClaim(this.employerClaimAddress, "generateDegreeClaim(uint256)"), + ).to.be.revertedWith("sender isn't allowed"); + + // Try to generate adult claim without registering identity + await expect( + passportID.connect(this.signers.alice).generateClaim(this.employerClaimAddress, "generateAdultClaim(uint256)"), + ).to.be.revertedWith("sender isn't allowed"); + }); + + it("should allow admin to add a new registrar for diplomaID and passportID", async function () { + // Test diplomaID + await expect(diplomaID.connect(this.signers.alice).addRegistrar(this.signers.bob.address)) + .to.emit(diplomaID, "RoleGranted") + .withArgs(await diplomaID.REGISTRAR_ROLE(), this.signers.bob.address, this.signers.alice.address); + + expect(await diplomaID.hasRole(await diplomaID.REGISTRAR_ROLE(), this.signers.bob.address)).to.be.true; + + // Test passportID + await expect(passportID.connect(this.signers.alice).addRegistrar(this.signers.bob.address)) + .to.emit(passportID, "RoleGranted") + .withArgs(await passportID.REGISTRAR_ROLE(), this.signers.bob.address, this.signers.alice.address); + + expect(await passportID.hasRole(await passportID.REGISTRAR_ROLE(), this.signers.bob.address)).to.be.true; + }); + + it("should allow admin to remove a registrar from diplomaID and passportID", async function () { + // Test diplomaID + await diplomaID.connect(this.signers.alice).addRegistrar(this.signers.bob.address); + await expect(diplomaID.connect(this.signers.alice).removeRegistrar(this.signers.bob.address)) + .to.emit(diplomaID, "RoleRevoked") + .withArgs(await diplomaID.REGISTRAR_ROLE(), this.signers.bob.address, this.signers.alice.address); + + expect(await diplomaID.hasRole(await diplomaID.REGISTRAR_ROLE(), this.signers.bob.address)).to.be.false; + + // Test passportID + await passportID.connect(this.signers.alice).addRegistrar(this.signers.bob.address); + await expect(passportID.connect(this.signers.alice).removeRegistrar(this.signers.bob.address)) + .to.emit(passportID, "RoleRevoked") + .withArgs(await passportID.REGISTRAR_ROLE(), this.signers.bob.address, this.signers.alice.address); + + expect(await passportID.hasRole(await passportID.REGISTRAR_ROLE(), this.signers.bob.address)).to.be.false; + }); + + it("should not allow non-admin to add a registrar to diplomaID and passportID", async function () { + // Test diplomaID + await expect( + diplomaID.connect(this.signers.carol).addRegistrar(this.signers.carol.address), + ).to.be.revertedWithCustomError(diplomaID, "AccessControlUnauthorizedAccount"); + + // Test passportID + await expect( + passportID.connect(this.signers.carol).addRegistrar(this.signers.carol.address), + ).to.be.revertedWithCustomError(passportID, "AccessControlUnauthorizedAccount"); + }); + + it("should not allow non-admin to remove a registrar from diplomaID and passportID", async function () { + // Test diplomaID + await diplomaID.connect(this.signers.alice).addRegistrar(this.signers.bob.address); + await expect( + diplomaID.connect(this.signers.carol).removeRegistrar(this.signers.bob.address), + ).to.be.revertedWithCustomError(diplomaID, "AccessControlUnauthorizedAccount"); + await diplomaID.connect(this.signers.alice).removeRegistrar(this.signers.bob.address); + + // Test passportID + await passportID.connect(this.signers.alice).addRegistrar(this.signers.bob.address); + await expect( + passportID.connect(this.signers.carol).removeRegistrar(this.signers.bob.address), + ).to.be.revertedWithCustomError(passportID, "AccessControlUnauthorizedAccount"); + await passportID.connect(this.signers.alice).removeRegistrar(this.signers.bob.address); + }); +}); diff --git a/hardhat/test/decIdentity/fixture/Diploma.fixture.ts b/hardhat/test/decIdentity/fixture/Diploma.fixture.ts new file mode 100644 index 0000000..ff0f4ba --- /dev/null +++ b/hardhat/test/decIdentity/fixture/Diploma.fixture.ts @@ -0,0 +1,12 @@ +import { ethers } from "hardhat"; + +import type { Diploma, IdMapping } from "../../../types"; +import { getSigners } from "../../signers"; + +export async function deployDiplomaFixture(idMapping: IdMapping): Promise { + const signers = await getSigners(); + const contractFactory = await ethers.getContractFactory("Diploma"); + const contract = await contractFactory.connect(signers.alice).deploy(idMapping); + await contract.waitForDeployment(); + return contract; +} diff --git a/hardhat/test/decIdentity/fixture/EmployerClaim.fixture.ts b/hardhat/test/decIdentity/fixture/EmployerClaim.fixture.ts new file mode 100644 index 0000000..9e5cd42 --- /dev/null +++ b/hardhat/test/decIdentity/fixture/EmployerClaim.fixture.ts @@ -0,0 +1,21 @@ +import { ethers } from "hardhat"; + +import type { Diploma, EmployerClaim, IdMapping, PassportID } from "../../../types"; +import { deployDiplomaFixture } from "./Diploma.fixture"; +import { deployIdMappingFixture } from "./IdMapping.fixture"; +import { deployPassportIDFixture } from "./PassportID.fixture"; + +export async function deployEmployerClaimFixture(): Promise<{ + employerClaim: EmployerClaim; + passportID: PassportID; + diploma: Diploma; + idMapping: IdMapping; +}> { + const idMapping = await deployIdMappingFixture(); + const passportID = await deployPassportIDFixture(idMapping); + const diploma = await deployDiplomaFixture(idMapping); + const EmployerClaimFactory = await ethers.getContractFactory("EmployerClaim"); + const employerClaim = await EmployerClaimFactory.deploy(idMapping, passportID, diploma); + await employerClaim.waitForDeployment(); + return { employerClaim, passportID, diploma, idMapping }; +} diff --git a/hardhat/test/decIdentity/fixture/IdMapping.fixture.ts b/hardhat/test/decIdentity/fixture/IdMapping.fixture.ts new file mode 100644 index 0000000..2964ae9 --- /dev/null +++ b/hardhat/test/decIdentity/fixture/IdMapping.fixture.ts @@ -0,0 +1,13 @@ +import { ethers } from "hardhat"; + +import type { IdMapping } from "../../../types"; +import { getSigners } from "../../signers"; + +export async function deployIdMappingFixture(): Promise { + const signers = await getSigners(); + + const IdMappingFactory = await ethers.getContractFactory("IdMapping"); + const idMapping = await IdMappingFactory.connect(signers.alice).deploy(); + await idMapping.waitForDeployment(); + return idMapping; +} diff --git a/hardhat/test/decIdentity/fixture/PassportID.fixture.ts b/hardhat/test/decIdentity/fixture/PassportID.fixture.ts new file mode 100644 index 0000000..3657eb2 --- /dev/null +++ b/hardhat/test/decIdentity/fixture/PassportID.fixture.ts @@ -0,0 +1,12 @@ +import { ethers } from "hardhat"; + +import type { IdMapping, PassportID } from "../../../types"; +import { getSigners } from "../../signers"; + +export async function deployPassportIDFixture(idMapping: IdMapping): Promise { + const signers = await getSigners(); + const contractFactory = await ethers.getContractFactory("PassportID"); + const contract = await contractFactory.connect(signers.alice).deploy(idMapping); + await contract.waitForDeployment(); + return contract; +} diff --git a/hardhat/test/decIdentity/idMapping.ts b/hardhat/test/decIdentity/idMapping.ts new file mode 100644 index 0000000..6d7a25e --- /dev/null +++ b/hardhat/test/decIdentity/idMapping.ts @@ -0,0 +1,106 @@ +import { expect } from "chai"; +import { ethers } from "hardhat"; + +import type { IdMapping } from "../../types"; +import { createInstance } from "../instance"; +import { getSigners, initSigners } from "../signers"; +import { deployIdMappingFixture } from "./fixture/IdMapping.fixture"; + +describe("IdMapping Contract", function () { + let idMapping: IdMapping; + + before(async function () { + await initSigners(); + this.signers = await getSigners(); + }); + + beforeEach(async function () { + // Deploy the contract + idMapping = await deployIdMappingFixture(); + this.idMappingAddress = await idMapping.getAddress(); + + // Set up accounts + this.instances = await createInstance(); + }); + + it("Should set the ID for an address", async function () { + // Set ID for addr1 + await idMapping.generateId(); + + // Check if the ID was set correctly + expect(await idMapping.getId(this.signers.alice)).to.equal(1); + }); + + it("Should set IDs for multiple addresses", async function () { + // Set IDs for addr1 and addr2 + await idMapping.connect(this.signers.alice).generateId(); + await idMapping.connect(this.signers.bob).generateId(); + + // Verify each address has the correct ID + expect(await idMapping.getId(this.signers.alice)).to.equal(1); + expect(await idMapping.getId(this.signers.bob)).to.equal(2); + }); + + it("Should retrieve address for a given ID", async function () { + // Generate ID for alice + await idMapping.connect(this.signers.alice).generateId(); + + // Get alice's address using their ID (1) + const retrievedAddress = await idMapping.getAddr(1); + expect(retrievedAddress).to.equal(await this.signers.alice.getAddress()); + + // Verify getting an invalid ID reverts + await expect(idMapping.getAddr(999)).to.be.revertedWithCustomError(idMapping, "InvalidId"); + }); + + it("Should not allow generating multiple IDs for same address", async function () { + await idMapping.connect(this.signers.alice).generateId(); + await expect(idMapping.connect(this.signers.alice).generateId()).to.be.revertedWithCustomError( + idMapping, + "IdAlreadyGenerated", + ); + }); + + it("Should fail when getting ID for zero address", async function () { + await expect(idMapping.getId(ethers.ZeroAddress)).to.be.revertedWithCustomError(idMapping, "InvalidAddress"); + }); + + it("Should fail when getting ID for unregistered address", async function () { + await expect(idMapping.getId(this.signers.alice.address)).to.be.revertedWithCustomError(idMapping, "NoIdGenerated"); + }); + + it("Should fail when getting address for invalid ID", async function () { + await expect(idMapping.getAddr(0)).to.be.revertedWithCustomError(idMapping, "InvalidId"); + + await expect(idMapping.getAddr(999)).to.be.revertedWithCustomError(idMapping, "InvalidId"); + }); + + it("Should allow owner to reset ID for an address", async function () { + // Generate ID first + await idMapping.connect(this.signers.alice).generateId(); + const userId = await idMapping.getId(this.signers.alice.address); + + // Reset ID + await idMapping.resetIdForAddress(this.signers.alice.address); + + // Verify ID is reset + await expect(idMapping.getId(this.signers.alice.address)).to.be.revertedWithCustomError(idMapping, "NoIdGenerated"); + + await expect(idMapping.getAddr(userId)).to.be.revertedWithCustomError(idMapping, "NoAddressFound"); + }); + + it("Should not allow non-owner to reset ID", async function () { + await idMapping.connect(this.signers.alice).generateId(); + + await expect( + idMapping.connect(this.signers.bob).resetIdForAddress(this.signers.alice.address), + ).to.be.revertedWithCustomError(idMapping, "OwnableUnauthorizedAccount"); + }); + + it("Should not allow resetting ID for unregistered address", async function () { + await expect(idMapping.resetIdForAddress(this.signers.alice.address)).to.be.revertedWithCustomError( + idMapping, + "NoIdGenerated", + ); + }); +}); diff --git a/hardhat/test/decIdentity/passportID.ts b/hardhat/test/decIdentity/passportID.ts new file mode 100644 index 0000000..9f2c6a1 --- /dev/null +++ b/hardhat/test/decIdentity/passportID.ts @@ -0,0 +1,163 @@ +import "@nomicfoundation/hardhat-chai-matchers"; +import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers"; +import { toBufferBE } from "bigint-buffer"; +import { expect } from "chai"; +import type { FhevmInstance } from "fhevmjs"; + +import type { Diploma, EmployerClaim, IdMapping, PassportID } from "../../types"; +import { createInstance } from "../instance"; +import { reencryptEbool, reencryptEbytes64, reencryptEuint8 } from "../reencrypt"; +import { getSigners, initSigners } from "../signers"; +import { bigIntToBytes64 } from "../utils"; +import { deployEmployerClaimFixture } from "./fixture/EmployerClaim.fixture"; + +// Helper function to convert bigint to bytes +export const bigIntToBytes256 = (value: bigint) => { + return new Uint8Array(toBufferBE(value, 256)); +}; + +describe("PassportID", function () { + let passportID: PassportID; + let employerClaim: EmployerClaim; + let diplomaID: Diploma; + let idMapping: IdMapping; + + // Initialize signers before running tests + before(async function () { + await initSigners(); + this.signers = await getSigners(); + }); + + // Deploy fresh contract instances before each test + beforeEach(async function () { + const deployment = await deployEmployerClaimFixture(); + employerClaim = deployment.employerClaim; + passportID = deployment.passportID; + diplomaID = deployment.diploma; + idMapping = deployment.idMapping; + + this.employerClaimAddress = await employerClaim.getAddress(); + this.diplomaAddress = await diplomaID.getAddress(); + this.passportIDAddress = await passportID.getAddress(); + this.idMappingAddress = await idMapping.getAddress(); + + this.instances = await createInstance(); + }); + + // Helper function to register identity + async function registerIdentity( + userId: bigint, + instance: FhevmInstance, + passportAddress: string, + signer: HardhatEthersSigner, + biodata = bigIntToBytes64(8n), + firstname = bigIntToBytes64(8n), + lastname = bigIntToBytes64(8n), + birthdate = 946681200n, // Sat Jan 01 2000 - 24 years old + ) { + const input = instance.createEncryptedInput(passportAddress, signer.address); + const encryptedData = await input + .addBytes64(biodata) + .addBytes64(firstname) + .addBytes64(lastname) + .add64(birthdate) + .encrypt(); + + await passportID + .connect(signer) + .registerIdentity( + userId, + encryptedData.handles[0], + encryptedData.handles[1], + encryptedData.handles[2], + encryptedData.handles[3], + encryptedData.inputProof, + ); + } + + // Helper function to setup reencryption + async function setupReencryption(instance: FhevmInstance, signer: HardhatEthersSigner, contractAddress: string) { + const { publicKey, privateKey } = instance.generateKeypair(); + const eip712 = instance.createEIP712(publicKey, contractAddress); + const signature = await signer.signTypedData(eip712.domain, { Reencrypt: eip712.types.Reencrypt }, eip712.message); + + return { publicKey, privateKey, signature: signature.replace("0x", "") }; + } + + // Test case: Register an identity successfully + it("should register an identity successfully", async function () { + await idMapping.connect(this.signers.alice).generateId(); + const userId = await idMapping.getId(this.signers.alice); + + await registerIdentity(userId, this.instances, this.passportIDAddress, this.signers.alice); + + expect(await passportID.registered(this.signers.alice.address)); + }); + + // Test case: Prevent duplicate registration for the same user + it("should prevent duplicate registration for the same user", async function () { + await idMapping.connect(this.signers.alice).generateId(); + const userId = await idMapping.getId(this.signers.alice); + + await registerIdentity(userId, this.instances, this.passportIDAddress, this.signers.alice); + + await expect( + registerIdentity(userId, this.instances, this.passportIDAddress, this.signers.alice), + ).to.be.revertedWithCustomError(passportID, "AlreadyRegistered"); + }); + + // Test case: Retrieve the registered identity + it("should retrieve the registered identity", async function () { + await idMapping.connect(this.signers.alice).generateId(); + const userId = await idMapping.getId(this.signers.alice); + + await registerIdentity(userId, this.instances, this.passportIDAddress, this.signers.alice); + + const firstnameHandleAlice = await passportID.getMyIdentityFirstname(userId); + + const reencryptedFirstname = await reencryptEbytes64( + this.signers.alice, + this.instances, + firstnameHandleAlice, + this.diplomaAddress, + ); + + expect(reencryptedFirstname).to.equal(8); + }); + + // Test case: Generate an adult claim + it("should generate an adult claim", async function () { + await idMapping.connect(this.signers.alice).generateId(); + const userId = await idMapping.getId(this.signers.alice); + + await registerIdentity(userId, this.instances, this.passportIDAddress, this.signers.alice); + + const tx = await passportID + .connect(this.signers.alice) + .generateClaim(this.employerClaimAddress, "generateAdultClaim(uint256)"); + + await expect(tx).to.emit(employerClaim, "AdultClaimGenerated"); + + const latestClaimUserId = await employerClaim.lastClaimId(); + const adultsClaim = await employerClaim.getAdultClaim(latestClaimUserId); + const reencrypted = await reencryptEbool(this.signers.bob, this.instances, adultsClaim, this.diplomaAddress); + + expect(reencrypted).to.equal(1); + }); + + // Test case: Should fail verification with invalid claim IDs + it("should fail verification with invalid claim IDs", async function () { + await idMapping.connect(this.signers.alice).generateId(); + const userId = await idMapping.getId(this.signers.alice); + + await expect(employerClaim.connect(this.signers.alice).verifyClaims(userId, 0, 1)).to.be.revertedWithCustomError( + employerClaim, + "InvalidClaimId", + ); + + await expect(employerClaim.connect(this.signers.alice).verifyClaims(userId, 1, 0)).to.be.revertedWithCustomError( + employerClaim, + "InvalidClaimId", + ); + }); +}); diff --git a/hardhat/test/fhevmjsMocked.ts b/hardhat/test/fhevmjsMocked.ts new file mode 100644 index 0000000..5c3f014 --- /dev/null +++ b/hardhat/test/fhevmjsMocked.ts @@ -0,0 +1,533 @@ +import { toBigIntBE, toBufferBE } from "bigint-buffer"; +import crypto from "crypto"; +import { Wallet, ethers } from "ethers"; +import hre from "hardhat"; +import { Keccak } from "sha3"; +import { isAddress } from "web3-validator"; + +import { + ACL_ADDRESS, + INPUTVERIFIER_ADDRESS, + KMSVERIFIER_ADDRESS, + PRIVATE_KEY_COPROCESSOR_ACCOUNT, + PRIVATE_KEY_KMS_SIGNER, +} from "./constants"; +import { insertSQL } from "./coprocessorUtils"; +import { awaitCoprocessor, getClearText } from "./coprocessorUtils"; + +enum Types { + ebool = 0, + euint4, + euint8, + euint16, + euint32, + euint64, + euint128, + eaddress, + euint256, + ebytes64, + ebytes128, + ebytes256, +} + +const sum = (arr: number[]) => arr.reduce((acc, val) => acc + val, 0); + +function bytesToBigInt(byteArray: Uint8Array): bigint { + if (!byteArray || byteArray?.length === 0) { + return BigInt(0); + } + const buffer = Buffer.from(byteArray); + const result = toBigIntBE(buffer); + return result; +} + +function createUintToUint8ArrayFunction(numBits: number) { + const numBytes = Math.ceil(numBits / 8); + return function (uint: number | bigint | boolean) { + const buffer = toBufferBE(BigInt(uint), numBytes); + + // concatenate 32 random bytes at the end of buffer to simulate encryption noise + const randomBytes = crypto.randomBytes(32); + const combinedBuffer = Buffer.concat([buffer, randomBytes]); + + let byteBuffer; + let totalBuffer; + + switch (numBits) { + case 2: // ebool takes 2 bits + byteBuffer = Buffer.from([Types.ebool]); + totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); + break; + case 4: + byteBuffer = Buffer.from([Types.euint4]); + totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); + break; + case 8: + byteBuffer = Buffer.from([Types.euint8]); + totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); + break; + case 16: + byteBuffer = Buffer.from([Types.euint16]); + totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); + break; + case 32: + byteBuffer = Buffer.from([Types.euint32]); + totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); + break; + case 64: + byteBuffer = Buffer.from([Types.euint64]); + totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); + break; + case 128: + byteBuffer = Buffer.from([Types.euint128]); + totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); + break; + case 160: + byteBuffer = Buffer.from([Types.eaddress]); + totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); + break; + case 256: + byteBuffer = Buffer.from([Types.euint256]); + totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); + break; + case 512: + byteBuffer = Buffer.from([Types.ebytes64]); + totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); + break; + case 1024: + byteBuffer = Buffer.from([Types.ebytes128]); + totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); + break; + case 2048: + byteBuffer = Buffer.from([Types.ebytes256]); + totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); + break; + default: + throw Error("Non-supported numBits"); + } + + return totalBuffer; + }; +} + +export const reencryptRequestMocked = async ( + handle: bigint, + privateKey: string, + publicKey: string, + signature: string, + contractAddress: string, + userAddress: string, +) => { + // Signature checking: + const domain = { + name: "Authorization token", + version: "1", + chainId: hre.network.config.chainId, + verifyingContract: contractAddress, + }; + const types = { + Reencrypt: [{ name: "publicKey", type: "bytes" }], + }; + const value = { + publicKey: `0x${publicKey}`, + }; + const signerAddress = ethers.verifyTypedData(domain, types, value, `0x${signature}`); + const normalizedSignerAddress = ethers.getAddress(signerAddress); + const normalizedUserAddress = ethers.getAddress(userAddress); + if (normalizedSignerAddress !== normalizedUserAddress) { + throw new Error("Invalid EIP-712 signature!"); + } + + // ACL checking + const aclArtifact = require("fhevm-core-contracts/artifacts/contracts/ACL.sol/ACL.json"); + const acl = await hre.ethers.getContractAt(aclArtifact.abi, ACL_ADDRESS); + const userAllowed = await acl.persistAllowed(handle, userAddress); + const contractAllowed = await acl.persistAllowed(handle, contractAddress); + const isAllowed = userAllowed && contractAllowed; + if (!isAllowed) { + throw new Error("User is not authorized to reencrypt this handle!"); + } + if (userAddress === contractAddress) { + throw new Error("userAddress should not be equal to contractAddress when requesting reencryption!"); + } + await awaitCoprocessor(); + return BigInt(await getClearText(handle)); +}; + +export const createEncryptedInputMocked = (contractAddress: string, userAddress: string) => { + if (!isAddress(contractAddress)) { + throw new Error("Contract address is not a valid address."); + } + + if (!isAddress(userAddress)) { + throw new Error("User address is not a valid address."); + } + + const values: bigint[] = []; + const bits: (keyof typeof ENCRYPTION_TYPES)[] = []; + return { + addBool(value: boolean | number | bigint) { + if (value == null) throw new Error("Missing value"); + if (typeof value !== "boolean" && typeof value !== "number" && typeof value !== "bigint") + throw new Error("The value must be a boolean, a number or a bigint."); + if ((typeof value !== "bigint" || typeof value !== "number") && Number(value) > 1) + throw new Error("The value must be 1 or 0."); + values.push(BigInt(value)); + bits.push(2); // ebool takes 2 bits instead of one: only exception in TFHE-rs + if (sum(bits) > 2048) throw Error("Packing more than 2048 bits in a single input ciphertext is unsupported"); + if (bits.length > 256) throw Error("Packing more than 256 variables in a single input ciphertext is unsupported"); + return this; + }, + add4(value: number | bigint) { + checkEncryptedValue(value, 4); + values.push(BigInt(value)); + bits.push(4); + if (sum(bits) > 2048) throw Error("Packing more than 2048 bits in a single input ciphertext is unsupported"); + if (bits.length > 256) throw Error("Packing more than 256 variables in a single input ciphertext is unsupported"); + return this; + }, + add8(value: number | bigint) { + checkEncryptedValue(value, 8); + values.push(BigInt(value)); + bits.push(8); + if (sum(bits) > 2048) throw Error("Packing more than 2048 bits in a single input ciphertext is unsupported"); + if (bits.length > 256) throw Error("Packing more than 256 variables in a single input ciphertext is unsupported"); + return this; + }, + add16(value: number | bigint) { + checkEncryptedValue(value, 16); + values.push(BigInt(value)); + bits.push(16); + if (sum(bits) > 2048) throw Error("Packing more than 2048 bits in a single input ciphertext is unsupported"); + if (bits.length > 256) throw Error("Packing more than 256 variables in a single input ciphertext is unsupported"); + return this; + }, + add32(value: number | bigint) { + checkEncryptedValue(value, 32); + values.push(BigInt(value)); + bits.push(32); + if (sum(bits) > 2048) throw Error("Packing more than 2048 bits in a single input ciphertext is unsupported"); + if (bits.length > 256) throw Error("Packing more than 256 variables in a single input ciphertext is unsupported"); + return this; + }, + add64(value: number | bigint) { + checkEncryptedValue(value, 64); + values.push(BigInt(value)); + bits.push(64); + if (sum(bits) > 2048) throw Error("Packing more than 2048 bits in a single input ciphertext is unsupported"); + if (bits.length > 256) throw Error("Packing more than 256 variables in a single input ciphertext is unsupported"); + return this; + }, + add128(value: number | bigint) { + checkEncryptedValue(value, 128); + values.push(BigInt(value)); + bits.push(128); + if (sum(bits) > 2048) throw Error("Packing more than 2048 bits in a single input ciphertext is unsupported"); + if (bits.length > 256) throw Error("Packing more than 256 variables in a single input ciphertext is unsupported"); + return this; + }, + addAddress(value: string) { + if (!isAddress(value)) { + throw new Error("The value must be a valid address."); + } + values.push(BigInt(value)); + bits.push(160); + if (sum(bits) > 2048) throw Error("Packing more than 2048 bits in a single input ciphertext is unsupported"); + if (bits.length > 256) throw Error("Packing more than 256 variables in a single input ciphertext is unsupported"); + return this; + }, + add256(value: number | bigint) { + checkEncryptedValue(value, 256); + values.push(BigInt(value)); + bits.push(256); + if (sum(bits) > 2048) throw Error("Packing more than 2048 bits in a single input ciphertext is unsupported"); + if (bits.length > 256) throw Error("Packing more than 256 variables in a single input ciphertext is unsupported"); + return this; + }, + addBytes64(value: Uint8Array) { + if (value.length !== 64) throw Error("Uncorrect length of input Uint8Array, should be 64 for an ebytes64"); + const bigIntValue = bytesToBigInt(value); + checkEncryptedValue(bigIntValue, 512); + values.push(bigIntValue); + bits.push(512); + if (sum(bits) > 2048) throw Error("Packing more than 2048 bits in a single input ciphertext is unsupported"); + if (bits.length > 256) throw Error("Packing more than 256 variables in a single input ciphertext is unsupported"); + return this; + }, + addBytes128(value: Uint8Array) { + if (value.length !== 128) throw Error("Uncorrect length of input Uint8Array, should be 128 for an ebytes128"); + const bigIntValue = bytesToBigInt(value); + checkEncryptedValue(bigIntValue, 1024); + values.push(bigIntValue); + bits.push(1024); + if (sum(bits) > 2048) throw Error("Packing more than 2048 bits in a single input ciphertext is unsupported"); + if (bits.length > 256) throw Error("Packing more than 256 variables in a single input ciphertext is unsupported"); + return this; + }, + addBytes256(value: Uint8Array) { + if (value.length !== 256) throw Error("Uncorrect length of input Uint8Array, should be 256 for an ebytes256"); + const bigIntValue = bytesToBigInt(value); + checkEncryptedValue(bigIntValue, 2048); + values.push(bigIntValue); + bits.push(2048); + if (sum(bits) > 2048) throw Error("Packing more than 2048 bits in a single input ciphertext is unsupported"); + if (bits.length > 256) throw Error("Packing more than 256 variables in a single input ciphertext is unsupported"); + return this; + }, + getValues() { + return values; + }, + getBits() { + return bits; + }, + resetValues() { + values.length = 0; + bits.length = 0; + return this; + }, + async encrypt() { + let encrypted = Buffer.alloc(0); + + bits.map((v, i) => { + encrypted = Buffer.concat([encrypted, createUintToUint8ArrayFunction(v)(values[i])]); + }); + + const encryptedArray = new Uint8Array(encrypted); + const hash = new Keccak(256).update(Buffer.from(encryptedArray)).digest(); + + const handles = bits.map((v, i) => { + const dataWithIndex = new Uint8Array(hash.length + 1); + dataWithIndex.set(hash, 0); + dataWithIndex.set([i], hash.length); + const finalHash = new Keccak(256).update(Buffer.from(dataWithIndex)).digest(); + const dataInput = new Uint8Array(32); + dataInput.set(finalHash, 0); + dataInput.set([i, ENCRYPTION_TYPES[v], 0], 29); + return dataInput; + }); + let inputProof = "0x" + numberToHex(handles.length); // for coprocessor : numHandles + numSignersKMS + hashCT + list_handles + signatureCopro + signatureKMSSigners (total len : 1+1+32+NUM_HANDLES*32+65+65*numSignersKMS) + // for native : numHandles + numSignersKMS + list_handles + signatureKMSSigners + bundleCiphertext (total len : 1+1+NUM_HANDLES*32+65*numSignersKMS+bundleCiphertext.length) + const numSigners = 1; // @note: only 1 signer in mocked mode for the moment + inputProof += numberToHex(numSigners); + //if (process.env.IS_COPROCESSOR === "true") { // @note: for now we support only the coprocessor mode, not native + // coprocessor + inputProof += hash.toString("hex"); + + const listHandlesStr = handles.map((i) => uint8ArrayToHexString(i)); + listHandlesStr.map((handle) => (inputProof += handle)); + const listHandles = listHandlesStr.map((i) => BigInt("0x" + i)); + const sigCoproc = await computeInputSignatureCopro( + "0x" + hash.toString("hex"), + listHandles, + userAddress, + contractAddress, + ); + inputProof += sigCoproc.slice(2); + + const signaturesKMS = await computeInputSignaturesKMS("0x" + hash.toString("hex"), userAddress, contractAddress); + signaturesKMS.map((sigKMS) => (inputProof += sigKMS.slice(2))); + listHandlesStr.map((handle, i) => insertSQL("0x" + handle, values[i])); + /*} else { + // native + const listHandlesStr = handles.map((i) => uint8ArrayToHexString(i)); + listHandlesStr.map((handle) => (inputProof += handle)); + const signaturesKMS = await computeInputSignaturesKMS( + "0x" + hash.toString("hex"), + userAddress, + contractAddress, + ); + signaturesKMS.map((sigKMS) => (inputProof += sigKMS.slice(2))); + listHandlesStr.map((handle, i) => insertSQL("0x" + handle, values[i])); + + inputProof += encrypted.toString("hex"); + }*/ + + return { + handles, + inputProof, + }; + }, + }; +}; + +function uint8ArrayToHexString(uint8Array: Uint8Array) { + return Array.from(uint8Array) + .map((byte) => byte.toString(16).padStart(2, "0")) + .join(""); +} + +function numberToHex(num: number) { + const hex = num.toString(16); + return hex.length % 2 ? "0" + hex : hex; +} + +const checkEncryptedValue = (value: number | bigint, bits: number) => { + if (value == null) throw new Error("Missing value"); + let limit; + if (bits >= 8) { + limit = BigInt(`0x${new Array(bits / 8).fill(null).reduce((v) => `${v}ff`, "")}`); + } else { + limit = BigInt(2 ** bits - 1); + } + if (typeof value !== "number" && typeof value !== "bigint") throw new Error("Value must be a number or a bigint."); + if (value > limit) { + throw new Error(`The value exceeds the limit for ${bits}bits integer (${limit.toString()}).`); + } +}; + +export const ENCRYPTION_TYPES = { + 2: 0, // ebool takes 2 bits + 4: 1, + 8: 2, + 16: 3, + 32: 4, + 64: 5, + 128: 6, + 160: 7, + 256: 8, + 512: 9, + 1024: 10, + 2048: 11, +}; + +async function computeInputSignatureCopro( + hash: string, + handlesList: bigint[], + userAddress: string, + contractAddress: string, +): Promise { + const privKeySigner = PRIVATE_KEY_COPROCESSOR_ACCOUNT; + const coprocSigner = new Wallet(privKeySigner).connect(ethers.provider); + const signature = await coprocSign(hash, handlesList, userAddress, contractAddress, coprocSigner); + return signature; +} + +async function computeInputSignaturesKMS( + hash: string, + userAddress: string, + contractAddress: string, +): Promise { + const signatures: string[] = []; + const numSigners = 1; // @note: only 1 KMS signer in mocked mode for now + for (let idx = 0; idx < numSigners; idx++) { + const privKeySigner = PRIVATE_KEY_KMS_SIGNER; + const kmsSigner = new ethers.Wallet(privKeySigner).connect(ethers.provider); + const signature = await kmsSign(hash, userAddress, contractAddress, kmsSigner); + signatures.push(signature); + } + return signatures; +} + +async function coprocSign( + hashOfCiphertext: string, + handlesList: bigint[], + userAddress: string, + contractAddress: string, + signer: Wallet, +): Promise { + const inputAdd = INPUTVERIFIER_ADDRESS; + const chainId = hre.__SOLIDITY_COVERAGE_RUNNING ? 31337 : network.config.chainId; + const aclAdd = ACL_ADDRESS; + + const domain = { + name: "InputVerifier", + version: "1", + chainId: chainId, + verifyingContract: inputAdd, + }; + + const types = { + CiphertextVerificationForCopro: [ + { + name: "aclAddress", + type: "address", + }, + { + name: "hashOfCiphertext", + type: "bytes32", + }, + { + name: "handlesList", + type: "uint256[]", + }, + { + name: "userAddress", + type: "address", + }, + { + name: "contractAddress", + type: "address", + }, + ], + }; + const message = { + aclAddress: aclAdd, + hashOfCiphertext: hashOfCiphertext, + handlesList: handlesList, + userAddress: userAddress, + contractAddress: contractAddress, + }; + + const signature = await signer.signTypedData(domain, types, message); + const sigRSV = ethers.Signature.from(signature); + const v = 27 + sigRSV.yParity; + const r = sigRSV.r; + const s = sigRSV.s; + + const result = r + s.substring(2) + v.toString(16); + return result; +} + +async function kmsSign( + hashOfCiphertext: string, + userAddress: string, + contractAddress: string, + signer: Wallet, +): Promise { + const kmsVerifierAdd = KMSVERIFIER_ADDRESS; + const chainId = hre.__SOLIDITY_COVERAGE_RUNNING ? 31337 : network.config.chainId; + const aclAdd = ACL_ADDRESS; + + const domain = { + name: "KMSVerifier", + version: "1", + chainId: chainId, + verifyingContract: kmsVerifierAdd, + }; + + const types = { + CiphertextVerificationForKMS: [ + { + name: "aclAddress", + type: "address", + }, + { + name: "hashOfCiphertext", + type: "bytes32", + }, + { + name: "userAddress", + type: "address", + }, + { + name: "contractAddress", + type: "address", + }, + ], + }; + const message = { + aclAddress: aclAdd, + hashOfCiphertext: hashOfCiphertext, + userAddress: userAddress, + contractAddress: contractAddress, + }; + + const signature = await signer.signTypedData(domain, types, message); + const sigRSV = ethers.Signature.from(signature); + const v = 27 + sigRSV.yParity; + const r = sigRSV.r; + const s = sigRSV.s; + + const result = r + s.substring(2) + v.toString(16); + return result; +} diff --git a/hardhat/test/instance.ts b/hardhat/test/instance.ts new file mode 100644 index 0000000..e310c2b --- /dev/null +++ b/hardhat/test/instance.ts @@ -0,0 +1,30 @@ +import { createEIP712, createInstance as createFhevmInstance, generateKeypair } from "fhevmjs"; +import { FhevmInstance } from "fhevmjs/node"; +import { network } from "hardhat"; + +import { ACL_ADDRESS, GATEWAY_URL, KMSVERIFIER_ADDRESS } from "./constants"; +import { createEncryptedInputMocked, reencryptRequestMocked } from "./fhevmjsMocked"; + +const kmsAdd = KMSVERIFIER_ADDRESS; +const aclAdd = ACL_ADDRESS; + +export const createInstance = async (): Promise => { + if (network.name === "hardhat") { + const instance = { + reencrypt: reencryptRequestMocked, + createEncryptedInput: createEncryptedInputMocked, + getPublicKey: () => "0xFFAA44433", + generateKeypair: generateKeypair, + createEIP712: createEIP712(network.config.chainId), + }; + return instance; + } else { + const instance = await createFhevmInstance({ + kmsContractAddress: kmsAdd, + aclContractAddress: aclAdd, + networkUrl: network.config.url, + gatewayUrl: GATEWAY_URL, + }); + return instance; + } +}; diff --git a/hardhat/test/mockedSetup.ts b/hardhat/test/mockedSetup.ts new file mode 100644 index 0000000..58e89f3 --- /dev/null +++ b/hardhat/test/mockedSetup.ts @@ -0,0 +1,56 @@ +import { ZeroAddress } from "ethers"; +import { HardhatRuntimeEnvironment } from "hardhat/types"; + +import { + ACL_ADDRESS, + FHEPAYMENT_ADDRESS, + GATEWAYCONTRACT_ADDRESS, + INPUTVERIFIER_ADDRESS, + KMSVERIFIER_ADDRESS, + PRIVATE_KEY_KMS_SIGNER, + TFHEEXECUTOR_ADDRESS, +} from "./constants"; + +const OneAddress = "0x0000000000000000000000000000000000000001"; + +export async function setCodeMocked(hre: HardhatRuntimeEnvironment) { + const aclArtifact = require("fhevm-core-contracts/artifacts/contracts/ACL.sol/ACL.json"); + const aclBytecode = aclArtifact.deployedBytecode; + await hre.network.provider.send("hardhat_setCode", [ACL_ADDRESS, aclBytecode]); + const execArtifact = require("fhevm-core-contracts/artifacts/contracts/TFHEExecutorWithEvents.sol/TFHEExecutorWithEvents.json"); + const execBytecode = execArtifact.deployedBytecode; + await hre.network.provider.send("hardhat_setCode", [TFHEEXECUTOR_ADDRESS, execBytecode]); + const kmsArtifact = require("fhevm-core-contracts/artifacts/contracts/KMSVerifier.sol/KMSVerifier.json"); + const kmsBytecode = kmsArtifact.deployedBytecode; + await hre.network.provider.send("hardhat_setCode", [KMSVERIFIER_ADDRESS, kmsBytecode]); + const inputArtifact = require("fhevm-core-contracts/artifacts/contracts/InputVerifier.coprocessor.sol/InputVerifier.json"); + const inputBytecode = inputArtifact.deployedBytecode; + await hre.network.provider.send("hardhat_setCode", [INPUTVERIFIER_ADDRESS, inputBytecode]); + const fhepaymentArtifact = require("fhevm-core-contracts/artifacts/contracts/FHEPayment.sol/FHEPayment.json"); + const fhepaymentBytecode = fhepaymentArtifact.deployedBytecode; + await hre.network.provider.send("hardhat_setCode", [FHEPAYMENT_ADDRESS, fhepaymentBytecode]); + const gatewayArtifact = require("fhevm-core-contracts/artifacts/gateway/GatewayContract.sol/GatewayContract.json"); + const gatewayBytecode = gatewayArtifact.deployedBytecode; + await hre.network.provider.send("hardhat_setCode", [GATEWAYCONTRACT_ADDRESS, gatewayBytecode]); + const zero = await impersonateAddress(hre, ZeroAddress, hre.ethers.parseEther("100")); + const one = await impersonateAddress(hre, OneAddress, hre.ethers.parseEther("100")); + const kmsSigner = new hre.ethers.Wallet(PRIVATE_KEY_KMS_SIGNER); + const kms = await hre.ethers.getContractAt(kmsArtifact.abi, KMSVERIFIER_ADDRESS); + await kms.connect(zero).initialize(OneAddress); + await kms.connect(one).addSigner(kmsSigner); + const input = await hre.ethers.getContractAt(inputArtifact.abi, INPUTVERIFIER_ADDRESS); + await input.connect(zero).initialize(OneAddress); + const gateway = await hre.ethers.getContractAt(gatewayArtifact.abi, GATEWAYCONTRACT_ADDRESS); + await gateway.connect(zero).addRelayer(ZeroAddress); +} + +export async function impersonateAddress(hre: HardhatRuntimeEnvironment, address: string, amount: bigint) { + // for mocked mode + await hre.network.provider.request({ + method: "hardhat_impersonateAccount", + params: [address], + }); + await hre.network.provider.send("hardhat_setBalance", [address, hre.ethers.toBeHex(amount)]); + const impersonatedSigner = await hre.ethers.getSigner(address); + return impersonatedSigner; +} diff --git a/hardhat/test/operatorPrices.json b/hardhat/test/operatorPrices.json new file mode 100644 index 0000000..d7f31a6 --- /dev/null +++ b/hardhat/test/operatorPrices.json @@ -0,0 +1,218 @@ +{ + "fheAdd": { + "binary": true, + "scalar": { "1": 65000, "2": 94000, "3": 133000, "4": 162000, "5": 188000, "6": 218000, "8": 253000 }, + "nonScalar": { "1": 65000, "2": 94000, "3": 133000, "4": 162000, "5": 188000, "6": 218000, "8": 253000 } + }, + "fheSub": { + "binary": true, + "scalar": { "1": 65000, "2": 94000, "3": 133000, "4": 162000, "5": 188000, "6": 218000, "8": 253000 }, + "nonScalar": { "1": 65000, "2": 94000, "3": 133000, "4": 162000, "5": 188000, "6": 218000, "8": 253000 } + }, + "fheMul": { + "binary": true, + "scalar": { "1": 88000, "2": 159000, "3": 208000, "4": 264000, "5": 356000, "6": 480000, "8": 647000 }, + "nonScalar": { "1": 150000, "2": 197000, "3": 262000, "4": 359000, "5": 641000, "6": 1145000, "8": 2045000 } + }, + "fheDiv": { + "binary": true, + "scalar": { "1": 139000, "2": 238000, "3": 314000, "4": 398000, "5": 584000, "6": 857000, "8": 1258000 } + }, + "fheRem": { + "binary": true, + "scalar": { "1": 286000, "2": 460000, "3": 622000, "4": 805000, "5": 1095000, "6": 1499000, "8": 2052000 } + }, + "fheBitAnd": { + "binary": true, + "scalar": { "0": 26000, "1": 32000, "2": 34000, "3": 34000, "4": 35000, "5": 38000, "6": 41000, "8": 44000 }, + "nonScalar": { "0": 26000, "1": 32000, "2": 34000, "3": 34000, "4": 35000, "5": 38000, "6": 41000, "8": 44000 } + }, + "fheBitOr": { + "binary": true, + "scalar": { "0": 26000, "1": 32000, "2": 34000, "3": 34000, "4": 35000, "5": 38000, "6": 41000, "8": 44000 }, + "nonScalar": { "0": 26000, "1": 32000, "2": 34000, "3": 34000, "4": 35000, "5": 38000, "6": 41000, "8": 44000 } + }, + "fheBitXor": { + "binary": true, + "scalar": { "0": 26000, "1": 32000, "2": 34000, "3": 34000, "4": 35000, "5": 38000, "6": 41000, "8": 44000 }, + "nonScalar": { "0": 26000, "1": 32000, "2": 34000, "3": 34000, "4": 35000, "5": 38000, "6": 41000, "8": 44000 } + }, + "fheShl": { + "binary": true, + "scalar": { "1": 35000, "2": 35000, "3": 35000, "4": 35000, "5": 38000, "6": 41000, "8": 44000 }, + "nonScalar": { "1": 116000, "2": 133000, "3": 153000, "4": 183000, "5": 227000, "6": 282000, "8": 350000 } + }, + "fheShr": { + "binary": true, + "scalar": { "1": 35000, "2": 35000, "3": 35000, "4": 35000, "5": 38000, "6": 41000, "8": 44000 }, + "nonScalar": { "1": 116000, "2": 133000, "3": 153000, "4": 183000, "5": 227000, "6": 282000, "8": 350000 } + }, + "fheRotl": { + "binary": true, + "scalar": { "1": 35000, "2": 35000, "3": 35000, "4": 35000, "5": 38000, "6": 41000, "8": 44000 }, + "nonScalar": { "1": 116000, "2": 133000, "3": 153000, "4": 183000, "5": 227000, "6": 282000, "8": 350000 } + }, + "fheRotr": { + "binary": true, + "scalar": { "1": 35000, "2": 35000, "3": 35000, "4": 35000, "5": 38000, "6": 41000, "8": 44000 }, + "nonScalar": { "1": 116000, "2": 133000, "3": 153000, "4": 183000, "5": 227000, "6": 282000, "8": 350000 } + }, + "fheEq": { + "binary": true, + "scalar": { + "0": 49000, + "1": 51000, + "2": 53000, + "3": 54000, + "4": 82000, + "5": 86000, + "6": 88000, + "7": 90000, + "8": 100000, + "9": 150000, + "10": 200000, + "11": 300000 + }, + "nonScalar": { + "0": 49000, + "1": 51000, + "2": 53000, + "3": 54000, + "4": 82000, + "5": 86000, + "6": 88000, + "7": 90000, + "8": 100000, + "9": 150000, + "10": 200000, + "11": 300000 + } + }, + "fheNe": { + "binary": true, + "scalar": { + "0": 49000, + "1": 51000, + "2": 53000, + "3": 54000, + "4": 82000, + "5": 86000, + "6": 88000, + "7": 90000, + "8": 100000, + "9": 150000, + "10": 200000, + "11": 300000 + }, + "nonScalar": { + "0": 49000, + "1": 51000, + "2": 53000, + "3": 54000, + "4": 82000, + "5": 86000, + "6": 88000, + "7": 90000, + "8": 100000, + "9": 150000, + "10": 200000, + "11": 300000 + } + }, + "fheGe": { + "binary": true, + "scalar": { "1": 70000, "2": 82000, "3": 105000, "4": 128000, "5": 156000, "6": 190000, "8": 231000 }, + "nonScalar": { "1": 70000, "2": 82000, "3": 105000, "4": 128000, "5": 156000, "6": 190000, "8": 231000 } + }, + "fheGt": { + "binary": true, + "scalar": { "1": 70000, "2": 82000, "3": 105000, "4": 128000, "5": 156000, "6": 190000, "8": 231000 }, + "nonScalar": { "1": 70000, "2": 82000, "3": 105000, "4": 128000, "5": 156000, "6": 190000, "8": 231000 } + }, + "fheLe": { + "binary": true, + "scalar": { "1": 70000, "2": 82000, "3": 105000, "4": 128000, "5": 156000, "6": 190000, "8": 231000 }, + "nonScalar": { "1": 70000, "2": 82000, "3": 105000, "4": 128000, "5": 156000, "6": 190000, "8": 231000 } + }, + "fheLt": { + "binary": true, + "scalar": { "1": 70000, "2": 82000, "3": 105000, "4": 128000, "5": 156000, "6": 190000, "8": 231000 }, + "nonScalar": { "1": 70000, "2": 82000, "3": 105000, "4": 128000, "5": 156000, "6": 190000, "8": 231000 } + }, + "fheMin": { + "binary": true, + "scalar": { "1": 121000, "2": 128000, "3": 150000, "4": 164000, "5": 192000, "6": 225000, "8": 264000 }, + "nonScalar": { "1": 121000, "2": 128000, "3": 153000, "4": 183000, "5": 210000, "6": 241000, "8": 277000 } + }, + "fheMax": { + "binary": true, + "scalar": { "1": 121000, "2": 128000, "3": 150000, "4": 164000, "5": 192000, "6": 225000, "8": 264000 }, + "nonScalar": { "1": 121000, "2": 128000, "3": 153000, "4": 183000, "5": 210000, "6": 241000, "8": 277000 } + }, + "fheNeg": { + "binary": false, + "types": { "1": 60000, "2": 95000, "3": 131000, "4": 160000, "5": 199000, "6": 248000, "8": 309000 } + }, + "fheNot": { + "binary": false, + "types": { "0": 30000, "1": 33000, "2": 34000, "3": 35000, "4": 36000, "5": 37000, "6": 38000, "8": 39000 } + }, + "cast": { + "binary": false, + "types": { "0": 200, "1": 200, "2": 200, "3": 200, "4": 200, "5": 200, "6": 200, "8": 200 } + }, + "trivialEncrypt": { + "binary": false, + "types": { + "0": 100, + "1": 100, + "2": 100, + "3": 200, + "4": 300, + "5": 600, + "6": 650, + "7": 700, + "8": 800, + "9": 1600, + "10": 3200, + "11": 6400 + } + }, + "ifThenElse": { + "binary": false, + "types": { + "0": 43000, + "1": 45000, + "2": 47000, + "3": 47000, + "4": 50000, + "5": 53000, + "6": 70000, + "7": 80000, + "8": 90000, + "9": 150000, + "10": 200000, + "11": 300000 + } + }, + "fheRand": { + "binary": false, + "types": { + "0": 100000, + "1": 100000, + "2": 100000, + "3": 100000, + "4": 100000, + "5": 100000, + "6": 100000, + "8": 100000, + "9": 200000, + "10": 300000, + "11": 400000 + } + }, + "fheRandBounded": { + "binary": false, + "types": { "1": 100000, "2": 100000, "3": 100000, "4": 100000, "5": 100000, "6": 100000, "8": 100000 } + } +} diff --git a/hardhat/test/reencrypt.ts b/hardhat/test/reencrypt.ts new file mode 100644 index 0000000..6b7b0d0 --- /dev/null +++ b/hardhat/test/reencrypt.ts @@ -0,0 +1,179 @@ +import { Signer } from "ethers"; +import { FhevmInstance } from "fhevmjs/node"; + +const EBOOL_T = 0; +const EUINT4_T = 1; +const EUINT8_T = 2; +const EUINT16_T = 3; +const EUINT32_T = 4; +const EUINT64_T = 5; +const EUINT128_T = 6; +const EUINT160_T = 7; // @dev It is the one for eaddresses. +const EUINT256_T = 8; +const EBYTES64_T = 9; +const EBYTES128_T = 10; +const EBYTES256_T = 11; + +export function verifyType(handle: bigint, expectedType: number) { + if (handle === 0n) { + throw "Handle is not initialized"; + } + + if (handle.toString(2).length > 256) { + throw "Handle is not a bytes32"; + } + + const typeCt = handle >> 8n; + + if (Number(typeCt % 256n) !== expectedType) { + throw "Wrong encrypted type for the handle"; + } +} + +export async function reencryptEbool( + signer: Signer, + instance: FhevmInstance, + handle: bigint, + contractAddress: string, +): Promise { + verifyType(handle, EBOOL_T); + return (await reencryptHandle(signer, instance, handle, contractAddress)) === 1n; +} + +export async function reencryptEuint4( + signer: Signer, + instance: FhevmInstance, + handle: bigint, + contractAddress: string, +): Promise { + verifyType(handle, EUINT4_T); + return reencryptHandle(signer, instance, handle, contractAddress); +} + +export async function reencryptEuint8( + signer: Signer, + instance: FhevmInstance, + handle: bigint, + contractAddress: string, +): Promise { + verifyType(handle, EUINT8_T); + return reencryptHandle(signer, instance, handle, contractAddress); +} + +export async function reencryptEuint16( + signer: Signer, + instance: FhevmInstance, + handle: bigint, + contractAddress: string, +): Promise { + verifyType(handle, EUINT16_T); + return reencryptHandle(signer, instance, handle, contractAddress); +} + +export async function reencryptEuint32( + signer: Signer, + instance: FhevmInstance, + handle: bigint, + contractAddress: string, +): Promise { + verifyType(handle, EUINT32_T); + return reencryptHandle(signer, instance, handle, contractAddress); +} + +export async function reencryptEuint64( + signer: Signer, + instance: FhevmInstance, + handle: bigint, + contractAddress: string, +): Promise { + verifyType(handle, EUINT64_T); + return reencryptHandle(signer, instance, handle, contractAddress); +} + +export async function reencryptEuint128( + signer: Signer, + instance: FhevmInstance, + handle: bigint, + contractAddress: string, +): Promise { + verifyType(handle, EUINT128_T); + return reencryptHandle(signer, instance, handle, contractAddress); +} + +export async function reencryptEaddress( + signer: Signer, + instance: FhevmInstance, + handle: bigint, + contractAddress: string, +): Promise { + verifyType(handle, EUINT160_T); + const addressAsUint160: bigint = await reencryptHandle(signer, instance, handle, contractAddress); + const handleStr = "0x" + addressAsUint160.toString(16).padStart(40, "0"); + return handleStr; +} + +export async function reencryptEuint256( + signer: Signer, + instance: FhevmInstance, + handle: bigint, + contractAddress: string, +): Promise { + verifyType(handle, EUINT256_T); + return reencryptHandle(signer, instance, handle, contractAddress); +} + +export async function reencryptEbytes64( + signer: Signer, + instance: FhevmInstance, + handle: bigint, + contractAddress: string, +): Promise { + verifyType(handle, EBYTES64_T); + return reencryptHandle(signer, instance, handle, contractAddress); +} + +export async function reencryptEbytes128( + signer: Signer, + instance: FhevmInstance, + handle: bigint, + contractAddress: string, +): Promise { + verifyType(handle, EBYTES128_T); + return reencryptHandle(signer, instance, handle, contractAddress); +} + +export async function reencryptEbytes256( + signer: Signer, + instance: FhevmInstance, + handle: bigint, + contractAddress: string, +): Promise { + verifyType(handle, EBYTES256_T); + return reencryptHandle(signer, instance, handle, contractAddress); +} + +/** + * @dev This function is to reencrypt handles. + * It does not verify types. + */ +async function reencryptHandle( + signer: Signer, + instance: FhevmInstance, + handle: bigint, + contractAddress: string, +): Promise { + const { publicKey: publicKey, privateKey: privateKey } = instance.generateKeypair(); + const eip712 = instance.createEIP712(publicKey, contractAddress); + const signature = await signer.signTypedData(eip712.domain, { Reencrypt: eip712.types.Reencrypt }, eip712.message); + + const reencryptedHandle = await instance.reencrypt( + handle, + privateKey, + publicKey, + signature.replace("0x", ""), + contractAddress, + await signer.getAddress(), + ); + + return reencryptedHandle; +} diff --git a/hardhat/test/signers.ts b/hardhat/test/signers.ts new file mode 100644 index 0000000..5fe72ca --- /dev/null +++ b/hardhat/test/signers.ts @@ -0,0 +1,26 @@ +import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers"; +import { ethers } from "hardhat"; + +import { ACCOUNT_NAMES } from "./constants"; + +type AccountNames = (typeof ACCOUNT_NAMES)[number]; + +export interface Signers { + [K in AccountNames]: HardhatEthersSigner; +} + +const signers: Signers = {} as Signers; + +export const initSigners = async (): Promise => { + if (Object.entries(signers).length === 0) { + const eSigners = await ethers.getSigners(); + for (let index = 0; index < ACCOUNT_NAMES.length; index++) { + const name = ACCOUNT_NAMES[index]; + signers[name] = eSigners[index]; + } + } +}; + +export const getSigners = async (): Promise => { + return signers; +}; diff --git a/hardhat/test/utils.ts b/hardhat/test/utils.ts new file mode 100644 index 0000000..39c5fb4 --- /dev/null +++ b/hardhat/test/utils.ts @@ -0,0 +1,317 @@ +import { toBufferBE } from "bigint-buffer"; +import { ethers, network } from "hardhat"; + +import { awaitCoprocessor, getClearText } from "./coprocessorUtils"; + +export const mineNBlocks = async (n: number) => { + for (let index = 0; index < n; index++) { + await ethers.provider.send("evm_mine"); + } +}; + +export const bigIntToBytes64 = (value: bigint) => { + return new Uint8Array(toBufferBE(value, 64)); +}; + +export const bigIntToBytes128 = (value: bigint) => { + return new Uint8Array(toBufferBE(value, 128)); +}; + +export const bigIntToBytes256 = (value: bigint) => { + return new Uint8Array(toBufferBE(value, 256)); +}; + +export const waitNBlocks = async (Nblocks: number) => { + const currentBlock = await ethers.provider.getBlockNumber(); + if (network.name === "hardhat") { + await produceDummyTransactions(Nblocks); + } + await waitForBlock(currentBlock + Nblocks); +}; + +export const produceDummyTransactions = async (blockCount: number) => { + let counter = blockCount; + while (counter >= 0) { + counter--; + const [signer] = await ethers.getSigners(); + const nullAddress = "0x0000000000000000000000000000000000000000"; + const tx = { + to: nullAddress, + value: 0n, + }; + const receipt = await signer.sendTransaction(tx); + await receipt.wait(); + } +}; + +const waitForBlock = (blockNumber: bigint | number) => { + return new Promise((resolve, reject) => { + const waitBlock = async (currentBlock: number) => { + if (blockNumber <= BigInt(currentBlock)) { + await ethers.provider.off("block", waitBlock); + resolve(blockNumber); + } + }; + ethers.provider.on("block", waitBlock).catch((err) => { + reject(err); + }); + }); +}; + +const EBOOL_T = 0; +const EUINT4_T = 1; +const EUINT8_T = 2; +const EUINT16_T = 3; +const EUINT32_T = 4; +const EUINT64_T = 5; +const EUINT128_T = 6; +const EUINT160_T = 7; // @dev It is the one for eaddresses. +const EUINT256_T = 8; +const EBYTES64_T = 9; +const EBYTES128_T = 10; +const EBYTES256_T = 11; + +function verifyType(handle: bigint, expectedType: number) { + if (handle === 0n) { + throw "Handle is not initialized"; + } + if (handle.toString(2).length > 256) { + throw "Handle is not a bytes32"; + } + const typeCt = handle >> 8n; + if (Number(typeCt % 256n) !== expectedType) { + throw "Wrong encrypted type for the handle"; + } +} + +export const debug = { + /** + * @debug + * This function is intended for debugging purposes only. + * It cannot be used in production code, since it requires the FHE private key for decryption. + * In production, decryption is only possible via an asyncronous on-chain call to the Gateway. + * + * @param {bigint} a handle to decrypt + * @returns {bool} + */ + decryptBool: async (handle: bigint): Promise => { + verifyType(handle, EBOOL_T); + if (network.name === "hardhat") { + await awaitCoprocessor(); + return (await getClearText(handle)) === "1"; + } else { + throw Error("The debug.decryptBool function can only be called in mocked mode"); + } + }, + + /** + * @debug + * This function is intended for debugging purposes only. + * It cannot be used in production code, since it requires the FHE private key for decryption. + * In production, decryption is only possible via an asyncronous on-chain call to the Gateway. + * + * @param {bigint} handle to decrypt + * @returns {bigint} + */ + decrypt4: async (handle: bigint): Promise => { + verifyType(handle, EUINT4_T); + if (network.name === "hardhat") { + await awaitCoprocessor(); + return BigInt(await getClearText(handle)); + } else { + throw Error("The debug.decrypt4 function can only be called in mocked mode"); + } + }, + + /** + * @debug + * This function is intended for debugging purposes only. + * It cannot be used in production code, since it requires the FHE private key for decryption. + * In production, decryption is only possible via an asyncronous on-chain call to the Gateway. + * + * @param {bigint} a handle to decrypt + * @returns {bigint} + */ + decrypt8: async (handle: bigint): Promise => { + verifyType(handle, EUINT8_T); + if (network.name === "hardhat") { + await awaitCoprocessor(); + return BigInt(await getClearText(handle)); + } else { + throw Error("The debug.decrypt8 function can only be called in mocked mode"); + } + }, + + /** + * @debug + * This function is intended for debugging purposes only. + * It cannot be used in production code, since it requires the FHE private key for decryption. + * In production, decryption is only possible via an asyncronous on-chain call to the Gateway. + * + * @param {bigint} handle to decrypt + * @returns {bigint} + */ + decrypt16: async (handle: bigint): Promise => { + verifyType(handle, EUINT16_T); + if (network.name === "hardhat") { + await awaitCoprocessor(); + return BigInt(await getClearText(handle)); + } else { + throw Error("The debug.decrypt16 function can only be called in mocked mode"); + } + }, + + /** + * @debug + * This function is intended for debugging purposes only. + * It cannot be used in production code, since it requires the FHE private key for decryption. + * In production, decryption is only possible via an asyncronous on-chain call to the Gateway. + * + * @param {bigint} handle to decrypt + * @returns {bigint} + */ + decrypt32: async (handle: bigint): Promise => { + verifyType(handle, EUINT32_T); + if (network.name === "hardhat") { + await awaitCoprocessor(); + return BigInt(await getClearText(handle)); + } else { + throw Error("The debug.decrypt32 function can only be called in mocked mode"); + } + }, + + /** + * @debug + * This function is intended for debugging purposes only. + * It cannot be used in production code, since it requires the FHE private key for decryption. + * In production, decryption is only possible via an asyncronous on-chain call to the Gateway. + * + * @param {bigint} handle to decrypt + * @returns {bigint} + */ + decrypt64: async (handle: bigint): Promise => { + verifyType(handle, EUINT64_T); + if (network.name === "hardhat") { + await awaitCoprocessor(); + return BigInt(await getClearText(handle)); + } else { + throw Error("The debug.decrypt64 function can only be called in mocked mode"); + } + }, + + /** + * @debug + * This function is intended for debugging purposes only. + * It cannot be used in production code, since it requires the FHE private key for decryption. + * In production, decryption is only possible via an asyncronous on-chain call to the Gateway. + * + * @param {bigint} handle to decrypt + * @returns {bigint} + */ + decrypt128: async (handle: bigint): Promise => { + verifyType(handle, EUINT128_T); + if (network.name === "hardhat") { + await awaitCoprocessor(); + return BigInt(await getClearText(handle)); + } else { + throw Error("The debug.decrypt128 function can only be called in mocked mode"); + } + }, + + /** + * @debug + * This function is intended for debugging purposes only. + * It cannot be used in production code, since it requires the FHE private key for decryption. + * In production, decryption is only possible via an asyncronous on-chain call to the Gateway. + * + * @param {bigint} handle to decrypt + * @returns {bigint} + */ + decrypt256: async (handle: bigint): Promise => { + verifyType(handle, EUINT256_T); + if (network.name === "hardhat") { + await awaitCoprocessor(); + return BigInt(await getClearText(handle)); + } else { + throw Error("The debug.decrypt256 function can only be called in mocked mode"); + } + }, + + /** + * @debug + * This function is intended for debugging purposes only. + * It cannot be used in production code, since it requires the FHE private key for decryption. + * In production, decryption is only possible via an asyncronous on-chain call to the Gateway. + * + * @param {bigint} handle to decrypt + * @returns {string} + */ + decryptAddress: async (handle: bigint): Promise => { + verifyType(handle, EUINT160_T); + if (network.name === "hardhat") { + await awaitCoprocessor(); + const bigintAdd = BigInt(await getClearText(handle)); + const handleStr = "0x" + bigintAdd.toString(16).padStart(40, "0"); + return handleStr; + } else { + throw Error("The debug.decryptAddress function can only be called in mocked mode"); + } + }, + + /** + * @debug + * This function is intended for debugging purposes only. + * It cannot be used in production code, since it requires the FHE private key for decryption. + * In production, decryption is only possible via an asyncronous on-chain call to the Gateway. + * + * @param {bigint} a handle to decrypt + * @returns {bigint} + */ + decryptEbytes64: async (handle: bigint): Promise => { + verifyType(handle, EBYTES64_T); + if (network.name === "hardhat") { + await awaitCoprocessor(); + return ethers.toBeHex(await getClearText(handle), 64); + } else { + throw Error("The debug.decryptEbytes64 function can only be called in mocked mode"); + } + }, + + /** + * @debug + * This function is intended for debugging purposes only. + * It cannot be used in production code, since it requires the FHE private key for decryption. + * In production, decryption is only possible via an asyncronous on-chain call to the Gateway. + * + * @param {bigint} handle to decrypt + * @returns {bigint} + */ + decryptEbytes128: async (handle: bigint): Promise => { + verifyType(handle, EBYTES128_T); + if (network.name === "hardhat") { + await awaitCoprocessor(); + return ethers.toBeHex(await getClearText(handle), 128); + } else { + throw Error("The debug.decryptEbytes128 function can only be called in mocked mode"); + } + }, + + /** + * @debug + * This function is intended for debugging purposes only. + * It cannot be used in production code, since it requires the FHE private key for decryption. + * In production, decryption is only possible via an asyncronous on-chain call to the Gateway. + * + * @param {bigint} handle to decrypt + * @returns {bigint} + */ + decryptEbytes256: async (handle: bigint): Promise => { + verifyType(handle, EBYTES256_T); + if (network.name === "hardhat") { + await awaitCoprocessor(); + return ethers.toBeHex(await getClearText(handle), 256); + } else { + throw Error("The debug.decryptEbytes256 function can only be called in mocked mode"); + } + }, +}; diff --git a/hardhat/tsconfig.json b/hardhat/tsconfig.json new file mode 100644 index 0000000..f5ef6d3 --- /dev/null +++ b/hardhat/tsconfig.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + "declaration": true, + "declarationMap": true, + "emitDecoratorMetadata": true, + "esModuleInterop": true, + "experimentalDecorators": true, + "forceConsistentCasingInFileNames": true, + "lib": ["es2020", "dom"], + "module": "commonjs", + "moduleResolution": "node", + "noImplicitAny": true, + "removeComments": true, + "resolveJsonModule": true, + "sourceMap": true, + "strict": true, + "target": "es2020" + }, + "exclude": ["node_modules"], + "files": ["./hardhat.config.ts"], + "include": ["src/**/*", "tasks/**/*", "test/**/*", "deploy/**/*", "types/"] +} From bb8cbab85f9601d0ebd6c8eac52c1df51aa648cc Mon Sep 17 00:00:00 2001 From: Aurora Poppyseed <30662672+poppyseedDev@users.noreply.github.com> Date: Fri, 13 Dec 2024 18:35:39 -0300 Subject: [PATCH 5/6] adding frontend and frontend visual --- .gitignore | 31 +- README.md | 182 +- contracts/.czrc | 3 - contracts/.editorconfig | 16 - contracts/.env.example | 2 - contracts/.gitignore | 31 - contracts/.gitpod.yml | 10 - contracts/.prettierignore | 22 - contracts/.prettierrc.yml | 23 - contracts/.solcover.js | 11 - contracts/.solhint.json | 24 - contracts/.solhintignore | 3 - contracts/CustomProvider.ts | 57 - contracts/LICENSE.md | 16 - contracts/README.md | 189 - contracts/contracts/MyConfidentialERC20.sol | 17 - contracts/contracts/TestAsyncDecrypt.sol | 549 -- .../contracts/confidentialCounter/sample1.sol | 31 - .../contracts/confidentialCounter/sample2.sol | 26 - .../contracts/confidentialCounter/sample3.sol | 51 - .../contracts/confidentialCounter/sample4.sol | 31 - contracts/contracts/decIdentity/Diploma.sol | 214 - .../contracts/decIdentity/EmployerClaim.sol | 207 - contracts/contracts/decIdentity/IdMapping.sol | 114 - .../contracts/decIdentity/PassportID.sol | 243 - contracts/deploy/deploy.ts | 27 - contracts/eslint.config.mjs | 17 - contracts/hardhat.config.ts | 150 - contracts/package.json | 100 - contracts/pnpm-lock.yaml | 8009 ---------------- contracts/tasks/accounts.ts | 39 - contracts/tasks/mint.ts | 27 - contracts/test/asyncDecrypt.ts | 251 - contracts/test/confidentialCounter/sample1.ts | 25 - contracts/test/confidentialCounter/sample2.ts | 30 - contracts/test/confidentialCounter/sample3.ts | 43 - contracts/test/confidentialCounter/sample4.ts | 71 - .../ConfidentialERC20.FHEGas.ts | 72 - .../ConfidentialERC20.fixture.ts | 14 - .../confidentialERC20/ConfidentialERC20.ts | 218 - contracts/test/constants.ts | 10 - contracts/test/coprocessorUtils.ts | 901 -- contracts/test/decIdentity/diploma.ts | 351 - .../decIdentity/fixture/Diploma.fixture.ts | 12 - .../fixture/EmployerClaim.fixture.ts | 21 - .../decIdentity/fixture/IdMapping.fixture.ts | 13 - .../decIdentity/fixture/PassportID.fixture.ts | 12 - contracts/test/decIdentity/idMapping.ts | 106 - contracts/test/decIdentity/passportID.ts | 164 - contracts/test/fhevmjsMocked.ts | 535 -- .../test/gatewayDecrypt/testAsyncDecrypt.ts | 333 - contracts/test/instance.ts | 30 - contracts/test/mockedSetup.ts | 91 - contracts/test/operatorsPrices.json | 218 - contracts/test/reencrypt.ts | 200 - contracts/test/signers.ts | 26 - contracts/test/utils.ts | 317 - contracts/tsconfig.json | 23 - {frontend => frontend-visual}/.eslintrc.json | 0 frontend-visual/.gitignore | 36 + frontend-visual/README.md | 38 + .../app/dapps/[slug]/page.tsx | 0 {frontend => frontend-visual}/app/favicon.ico | Bin .../app/fonts/Telegraf UltraBold 800.woff | Bin .../app/fonts/Telegraf UltraLight 200.woff | Bin ...ular_272984568a25d8528fe2de8b20b29011.woff | Bin {frontend => frontend-visual}/app/globals.css | 0 {frontend => frontend-visual}/app/layout.tsx | 0 {frontend => frontend-visual}/app/page.tsx | 0 {frontend => frontend-visual}/components.json | 0 .../components/ConnectButton.tsx | 0 .../components/DAppCard.tsx | 0 .../components/Header.tsx | 0 .../components/ui/button.tsx | 0 .../components/ui/dropdown-menu.tsx | 0 {frontend => frontend-visual}/lib/utils.ts | 0 {frontend => frontend-visual}/next.config.mjs | 0 frontend-visual/package-lock.json | 5188 ++++++++++ frontend-visual/package.json | 34 + {frontend => frontend-visual}/pnpm-lock.yaml | 0 .../postcss.config.mjs | 0 .../public/fonts/Telegraf UltraBold 800.woff | Bin .../public/fonts/Telegraf UltraLight 200.woff | Bin ...ular_272984568a25d8528fe2de8b20b29011.woff | Bin {frontend => frontend-visual}/public/test.png | Bin .../tailwind.config.ts | 0 frontend-visual/tsconfig.json | 26 + frontend/.env.example | 3 + frontend/.eslintrc.cjs | 30 + frontend/.gitignore | 55 +- frontend/.prettierrc | 3 + frontend/LICENSE | 28 + frontend/README.md | 41 +- frontend/index.html | 13 + frontend/package-lock.json | 8458 +++++++++++++++++ frontend/package.json | 57 +- frontend/public/vite.svg | 1 + frontend/scripts/dev.js | 23 + frontend/src/App.css | 10 + frontend/src/App.tsx | 37 + frontend/src/components/Connect/Connect.css | 11 + frontend/src/components/Connect/Connect.tsx | 152 + frontend/src/components/Connect/index.ts | 1 + frontend/src/components/Devnet/Devnet.css | 12 + frontend/src/components/Devnet/Devnet.tsx | 276 + frontend/src/components/Devnet/Devnet.tsx.bak | 102 + frontend/src/components/Devnet/index.ts | 1 + frontend/src/fhevmStorage.ts | 75 + frontend/src/fhevmjs.ts | 108 + frontend/src/fhevmjsMocked.ts | 380 + frontend/src/index.css | 69 + frontend/src/main.tsx | 10 + frontend/src/vite-env.d.ts | 7 + frontend/tsconfig.json | 35 +- frontend/tsconfig.node.json | 10 + frontend/vite.config.ts | 36 + hardhat/test/decIdentity/passportID.ts | 2 +- 117 files changed, 15293 insertions(+), 14634 deletions(-) delete mode 100644 contracts/.czrc delete mode 100644 contracts/.editorconfig delete mode 100644 contracts/.env.example delete mode 100644 contracts/.gitignore delete mode 100644 contracts/.gitpod.yml delete mode 100644 contracts/.prettierignore delete mode 100644 contracts/.prettierrc.yml delete mode 100644 contracts/.solcover.js delete mode 100644 contracts/.solhint.json delete mode 100644 contracts/.solhintignore delete mode 100644 contracts/CustomProvider.ts delete mode 100644 contracts/LICENSE.md delete mode 100644 contracts/README.md delete mode 100644 contracts/contracts/MyConfidentialERC20.sol delete mode 100644 contracts/contracts/TestAsyncDecrypt.sol delete mode 100644 contracts/contracts/confidentialCounter/sample1.sol delete mode 100644 contracts/contracts/confidentialCounter/sample2.sol delete mode 100644 contracts/contracts/confidentialCounter/sample3.sol delete mode 100644 contracts/contracts/confidentialCounter/sample4.sol delete mode 100644 contracts/contracts/decIdentity/Diploma.sol delete mode 100644 contracts/contracts/decIdentity/EmployerClaim.sol delete mode 100644 contracts/contracts/decIdentity/IdMapping.sol delete mode 100644 contracts/contracts/decIdentity/PassportID.sol delete mode 100644 contracts/deploy/deploy.ts delete mode 100644 contracts/eslint.config.mjs delete mode 100644 contracts/hardhat.config.ts delete mode 100644 contracts/package.json delete mode 100644 contracts/pnpm-lock.yaml delete mode 100644 contracts/tasks/accounts.ts delete mode 100644 contracts/tasks/mint.ts delete mode 100644 contracts/test/asyncDecrypt.ts delete mode 100644 contracts/test/confidentialCounter/sample1.ts delete mode 100644 contracts/test/confidentialCounter/sample2.ts delete mode 100644 contracts/test/confidentialCounter/sample3.ts delete mode 100644 contracts/test/confidentialCounter/sample4.ts delete mode 100644 contracts/test/confidentialERC20/ConfidentialERC20.FHEGas.ts delete mode 100644 contracts/test/confidentialERC20/ConfidentialERC20.fixture.ts delete mode 100644 contracts/test/confidentialERC20/ConfidentialERC20.ts delete mode 100644 contracts/test/constants.ts delete mode 100644 contracts/test/coprocessorUtils.ts delete mode 100644 contracts/test/decIdentity/diploma.ts delete mode 100644 contracts/test/decIdentity/fixture/Diploma.fixture.ts delete mode 100644 contracts/test/decIdentity/fixture/EmployerClaim.fixture.ts delete mode 100644 contracts/test/decIdentity/fixture/IdMapping.fixture.ts delete mode 100644 contracts/test/decIdentity/fixture/PassportID.fixture.ts delete mode 100644 contracts/test/decIdentity/idMapping.ts delete mode 100644 contracts/test/decIdentity/passportID.ts delete mode 100644 contracts/test/fhevmjsMocked.ts delete mode 100644 contracts/test/gatewayDecrypt/testAsyncDecrypt.ts delete mode 100644 contracts/test/instance.ts delete mode 100644 contracts/test/mockedSetup.ts delete mode 100644 contracts/test/operatorsPrices.json delete mode 100644 contracts/test/reencrypt.ts delete mode 100644 contracts/test/signers.ts delete mode 100644 contracts/test/utils.ts delete mode 100644 contracts/tsconfig.json rename {frontend => frontend-visual}/.eslintrc.json (100%) create mode 100644 frontend-visual/.gitignore create mode 100644 frontend-visual/README.md rename {frontend => frontend-visual}/app/dapps/[slug]/page.tsx (100%) rename {frontend => frontend-visual}/app/favicon.ico (100%) rename {frontend => frontend-visual}/app/fonts/Telegraf UltraBold 800.woff (100%) rename {frontend => frontend-visual}/app/fonts/Telegraf UltraLight 200.woff (100%) rename {frontend => frontend-visual}/app/fonts/TelegrafRegular_272984568a25d8528fe2de8b20b29011.woff (100%) rename {frontend => frontend-visual}/app/globals.css (100%) rename {frontend => frontend-visual}/app/layout.tsx (100%) rename {frontend => frontend-visual}/app/page.tsx (100%) rename {frontend => frontend-visual}/components.json (100%) rename {frontend => frontend-visual}/components/ConnectButton.tsx (100%) rename {frontend => frontend-visual}/components/DAppCard.tsx (100%) rename {frontend => frontend-visual}/components/Header.tsx (100%) rename {frontend => frontend-visual}/components/ui/button.tsx (100%) rename {frontend => frontend-visual}/components/ui/dropdown-menu.tsx (100%) rename {frontend => frontend-visual}/lib/utils.ts (100%) rename {frontend => frontend-visual}/next.config.mjs (100%) create mode 100644 frontend-visual/package-lock.json create mode 100644 frontend-visual/package.json rename {frontend => frontend-visual}/pnpm-lock.yaml (100%) rename {frontend => frontend-visual}/postcss.config.mjs (100%) rename {frontend => frontend-visual}/public/fonts/Telegraf UltraBold 800.woff (100%) rename {frontend => frontend-visual}/public/fonts/Telegraf UltraLight 200.woff (100%) rename {frontend => frontend-visual}/public/fonts/TelegrafRegular_272984568a25d8528fe2de8b20b29011.woff (100%) rename {frontend => frontend-visual}/public/test.png (100%) rename {frontend => frontend-visual}/tailwind.config.ts (100%) create mode 100644 frontend-visual/tsconfig.json create mode 100644 frontend/.env.example create mode 100644 frontend/.eslintrc.cjs create mode 100644 frontend/.prettierrc create mode 100644 frontend/LICENSE create mode 100644 frontend/index.html create mode 100644 frontend/package-lock.json create mode 100644 frontend/public/vite.svg create mode 100644 frontend/scripts/dev.js create mode 100644 frontend/src/App.css create mode 100644 frontend/src/App.tsx create mode 100644 frontend/src/components/Connect/Connect.css create mode 100644 frontend/src/components/Connect/Connect.tsx create mode 100644 frontend/src/components/Connect/index.ts create mode 100644 frontend/src/components/Devnet/Devnet.css create mode 100644 frontend/src/components/Devnet/Devnet.tsx create mode 100644 frontend/src/components/Devnet/Devnet.tsx.bak create mode 100644 frontend/src/components/Devnet/index.ts create mode 100644 frontend/src/fhevmStorage.ts create mode 100644 frontend/src/fhevmjs.ts create mode 100644 frontend/src/fhevmjsMocked.ts create mode 100644 frontend/src/index.css create mode 100644 frontend/src/main.tsx create mode 100644 frontend/src/vite-env.d.ts create mode 100644 frontend/tsconfig.node.json create mode 100644 frontend/vite.config.ts diff --git a/.gitignore b/.gitignore index f1fbdfd..be47843 100644 --- a/.gitignore +++ b/.gitignore @@ -1,31 +1,2 @@ -# directories -.coverage_artifacts -.coverage_cache -.coverage_contracts -artifacts -build -cache -coverage -dist -node_modules -types -deployments -kms-fhe-keys/ -network-fhe-keys/ -fhevmTemp/ -abi/ - -# files -*.env -*.log -.env.docker .DS_Store -.pnp.* -coverage.json -package-lock.json -yarn.lock - -res/ -running_node/ - -docker-compose/docker-compose-full.yml +.env diff --git a/README.md b/README.md index eca10d0..772df10 100644 --- a/README.md +++ b/README.md @@ -1,185 +1,51 @@ -# Hardhat Template [![Open in Gitpod][gitpod-badge]][gitpod] [![Github Actions][gha-badge]][gha] [![Hardhat][hardhat-badge]][hardhat] [![License: MIT][license-badge]][license] - -[gitpod]: https://gitpod.io/#https://github.com/zama-ai/fhevm-hardhat-template -[gitpod-badge]: https://img.shields.io/badge/Gitpod-Open%20in%20Gitpod-FFB45B?logo=gitpod -[gha]: https://github.com/zama-ai/fhevm-hardhat-template/actions -[gha-badge]: https://github.com/zama-ai/fhevm-hardhat-template/actions/workflows/ci.yml/badge.svg -[hardhat]: https://hardhat.org/ -[hardhat-badge]: https://img.shields.io/badge/Built%20with-Hardhat-FFDB1C.svg -[license]: https://opensource.org/licenses/MIT -[license-badge]: https://img.shields.io/badge/License-MIT-blue.svg - -A Hardhat-based template for developing Solidity smart contracts, with sensible defaults. - -- [Hardhat](https://github.com/nomiclabs/hardhat): compile, run and test smart contracts -- [TypeChain](https://github.com/ethereum-ts/TypeChain): generate TypeScript bindings for smart contracts -- [Ethers](https://github.com/ethers-io/ethers.js/): renowned Ethereum library and wallet implementation -- [Solhint](https://github.com/protofire/solhint): code linter -- [Solcover](https://github.com/sc-forks/solidity-coverage): code coverage -- [Prettier Plugin Solidity](https://github.com/prettier-solidity/prettier-plugin-solidity): code formatter - -## Getting Started - -Click the [`Use this template`](https://github.com/zama-ai/fhevm-hardhat-template/generate) button at the top of the -page to create a new repository with this repo as the initial state. - -## Features - -This template builds upon the frameworks and libraries mentioned above, so for details about their specific features, -please consult their respective documentations. - -For example, for Hardhat, you can refer to the [Hardhat Tutorial](https://hardhat.org/tutorial) and the -[Hardhat Docs](https://hardhat.org/docs). You might be in particular interested in reading the -[Testing Contracts](https://hardhat.org/tutorial/testing-contracts) section. - -### Sensible Defaults - -This template comes with sensible default configurations in the following files: - -```text -├── .editorconfig -├── .eslintignore -├── .eslintrc.yml -├── .gitignore -├── .prettierignore -├── .prettierrc.yml -├── .solcover.js -├── .solhint.json -└── hardhat.config.ts -``` - -### VSCode Integration - -This template is IDE agnostic, but for the best user experience, you may want to use it in VSCode alongside Nomic -Foundation's [Solidity extension](https://marketplace.visualstudio.com/items?itemName=NomicFoundation.hardhat-solidity). - -### GitHub Actions - -This template comes with GitHub Actions pre-configured. Your contracts will be linted and tested on every push and pull -request made to the `main` branch. +# fhevm-react-template -Note though that to make this work, you must use your `INFURA_API_KEY` and your `MNEMONIC` as GitHub secrets. +This is an example dApp made with React.js to let users do transfers of a `ConfidentialERC20` token on fhEVM. It contains also a button to request the decryption of an encrypted secret value. -You can edit the CI script in [.github/workflows/ci.yml](./.github/workflows/ci.yml). +## How to use this repo -## Usage +You can either deploy the dApp on the real fhEVM coprocessor on the Ethereum Sepolia testnet, or on a local Hardhat node (i.e a mocked corpocessor). -### Pre Requisites +### How to deploy on Sepolia -Install [pnpm](https://pnpm.io/installation) +First, before launching the React app, you must deploy the `ConfidentialERC20` smart contract and mint the first few tokens. +To do this, go to the `hardhat/` directory, and follow all the instructions from the [`README`](/hardhat/README.md) there to deploy and mint the first tokens with Alice's account, i.e until you are able to run the following command: -Before being able to run any command, you need to create a `.env` file and set a BIP-39 compatible mnemonic as the `MNEMONIC` -environment variable. You can follow the example in `.env.example` or start with the following command: - -```sh -cp .env.example .env ``` - -If you don't already have a mnemonic, you can use this [website](https://iancoleman.io/bip39/) to generate one. An alternative, if you have [foundry](https://book.getfoundry.sh/getting-started/installation) installed is to use the `cast wallet new-mnemonic` command. - -Then, install all needed dependencies - please **_make sure to use Node v20_** or more recent: - -```sh -pnpm install +npm run deploy-sepolia ``` -### Compile +> **Note:** Be careful to use your own private mnemonic key in this case, in the `.env` file (do not reuse the public values from `.env.example`!). -Compile the smart contracts with Hardhat: +After you succesfully run the Sepolia deployment script, go to the `frontend/` directory, and just run those two commands: -```sh -pnpm compile ``` - -### TypeChain - -Compile the smart contracts and generate TypeChain bindings: - -```sh -pnpm typechain +npm install +npm run dev ``` -### Test - -Run the tests with Hardhat - this will run the tests on a local hardhat node in mocked mode (i.e the FHE operations and decryptions will be simulated by default): - -```sh -pnpm test -``` +This will launch the front-end of the dApp from a local Vite server, which will be available at the following URL: [`http://localhost:4173/`](http://localhost:4173/) . You can connect to the dApp with a Web3 wallet such as Metamask and start transferring tokens, reencrypt and read your balance, or request the decryption of the encrypted secret on Sepolia. -### Lint Solidity +### How to use in Mocked mode -Lint the Solidity code: +First go to the `hardhat/` directory : define a new `.env` file - in mocked mode, simply doing a copy `cp .env.example .env` is doable, but you can also you your own private mnemonic - then install all packages with +`npm i`. Now you can launch the hardhat local node with: -```sh -pnpm lint:sol ``` - -### Lint TypeScript - -Lint the TypeScript code: - -```sh -pnpm lint:ts +npx hardhat node ``` +This will also launch a mocked instance of the coprocessor. -### Clean - -Delete the smart contract artifacts, the coverage reports and the Hardhat cache: +You can then go to the `frontend/` directory, and just run those two commands: -```sh -pnpm clean ``` - -### Mocked mode - -The mocked mode allows faster testing and the ability to analyze coverage of the tests. In this mocked version, -encrypted types are not really encrypted, and the tests are run on the original version of the EVM, on a local hardhat -network instance. To run the tests in mocked mode, you can use directly the following command: - -```bash -pnpm test -``` - -To analyze the coverage of the tests (in mocked mode necessarily, as this cannot be done on the real fhEVM node), you -can use this command : - -```bash -pnpm coverage -``` - -Then open the file `coverage/index.html`. You can see there which line or branch for each contract which has been -covered or missed by your test suite. This allows increased security by pointing out missing branches not covered yet by -the current tests. - -> [!Note] -> Due to intrinsic limitations of the original EVM, the mocked version differs in rare edge cases from the real fhEVM, the main difference is the gas consumption for the FHE operations (native gas is around 5% underestimated in mocked mode). This means that before deploying to production, developers should still run the tests with the original fhEVM node, as a final check - i.e in non-mocked mode (see next section). - -### Non-mocked mode - -To run your test on a real fhevm node, you can use the coprocessor deployed on the Sepolia test network. To do this, ensure you are using a valid value `SEPOLIA_RPC_URL` in your `.env` file. Then you should use the following command: - -```bash -npx hardhat test [PATH_TO_YOUR_TEST] --network sepolia +npm install +npm run dev-mocked ``` -The `--network sepolia` flag will make your test run on a real fhevm coprocessor. - -> [!Note] -> For this test to succeed, first ensure you set your own private `MNEMONIC` variable in the `.env` file and then ensure you have funded your test accounts on Sepolia. For example you can use the following command to get the corresponding private keys associated with the first `5` accounts derived from the mnemonic: -``` -npx hardhat get-accounts --num-accounts 5 -``` -This will let you add them to the Metamask app, to easily fund them from your personal wallet. - -If you don't own already Sepolia test tokens, you can for example use a free faucet such as [https://sepolia-faucet.pk910.de/](https://sepolia-faucet.pk910.de/). - -### Syntax Highlighting - -If you use VSCode, you can get Solidity syntax highlighting with the -[hardhat-solidity](https://marketplace.visualstudio.com/items?itemName=NomicFoundation.hardhat-solidity) extension. +The dApp will be available again at: [`http://localhost:4173/`](http://localhost:4173/) . You can connect to the dApp with a Web3 wallet such as Metamask and start transferring tokens, reencrypt and read your balance, or request the decryption of the encrypted. This time, the only difference is that it will ask you to connect to the Hardhat network instead of Sepolia, so make sure to have added the Hardhat network to your Metamask wallet in order to be able to use the dApp with the mocked coprocessor. You can find instructions to configure Metamask adequatly [here](https://support.chainstack.com/hc/en-us/articles/4408642503449-Using-MetaMask-with-a-Hardhat-node). -## License +#### Troubleshooting -This project is licensed under MIT. +**_Invalid nonce errors:_** This is a common issue everytime you restart your local Hardhat node and you want to reuse the same accounts in Metamask. You should remember to reset the nonce of the accounts you used the last time with Hardhat. To reset the account's transaction history and the nonce, open Metamask and select the Hardhat network, click on your account followed by `Settings -> Advanced -> Clear activity tab data`. diff --git a/contracts/.czrc b/contracts/.czrc deleted file mode 100644 index d1bcc20..0000000 --- a/contracts/.czrc +++ /dev/null @@ -1,3 +0,0 @@ -{ - "path": "cz-conventional-changelog" -} diff --git a/contracts/.editorconfig b/contracts/.editorconfig deleted file mode 100644 index 6fd96c1..0000000 --- a/contracts/.editorconfig +++ /dev/null @@ -1,16 +0,0 @@ -# EditorConfig http://EditorConfig.org - -# top-most EditorConfig file -root = true - -# All files -[*] -charset = utf-8 -end_of_line = lf -indent_size = 2 -indent_style = space -insert_final_newline = true -trim_trailing_whitespace = true - -[*.sol] -indent_size = 4 diff --git a/contracts/.env.example b/contracts/.env.example deleted file mode 100644 index 37f0cdc..0000000 --- a/contracts/.env.example +++ /dev/null @@ -1,2 +0,0 @@ -export MNEMONIC="exchange vintage ocean narrow danger return culture ignore trim solve clock hidden buddy wise emotion" -export SEPOLIA_RPC_URL="https://sepolia.infura.io/v3/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ No newline at end of file diff --git a/contracts/.gitignore b/contracts/.gitignore deleted file mode 100644 index f1fbdfd..0000000 --- a/contracts/.gitignore +++ /dev/null @@ -1,31 +0,0 @@ -# directories -.coverage_artifacts -.coverage_cache -.coverage_contracts -artifacts -build -cache -coverage -dist -node_modules -types -deployments -kms-fhe-keys/ -network-fhe-keys/ -fhevmTemp/ -abi/ - -# files -*.env -*.log -.env.docker -.DS_Store -.pnp.* -coverage.json -package-lock.json -yarn.lock - -res/ -running_node/ - -docker-compose/docker-compose-full.yml diff --git a/contracts/.gitpod.yml b/contracts/.gitpod.yml deleted file mode 100644 index dd2444f..0000000 --- a/contracts/.gitpod.yml +++ /dev/null @@ -1,10 +0,0 @@ -image: "gitpod/workspace-node:latest" - -tasks: - - init: "pnpm install" - -vscode: - extensions: - - "esbenp.prettier-vscode" - - "NomicFoundation.hardhat-solidity" - - "ritwickdey.LiveServer" diff --git a/contracts/.prettierignore b/contracts/.prettierignore deleted file mode 100644 index d1401c9..0000000 --- a/contracts/.prettierignore +++ /dev/null @@ -1,22 +0,0 @@ -# directories -.coverage_artifacts -.coverage_cache -.coverage_contracts -artifacts -build -cache -coverage -dist -node_modules -types - -# files -*.env -*.log -.DS_Store -.pnp.* -coverage.json -package-lock.json -pnpm-lock.yaml -yarn.lock -README.md \ No newline at end of file diff --git a/contracts/.prettierrc.yml b/contracts/.prettierrc.yml deleted file mode 100644 index 56221e3..0000000 --- a/contracts/.prettierrc.yml +++ /dev/null @@ -1,23 +0,0 @@ -bracketSpacing: true -plugins: - - "@trivago/prettier-plugin-sort-imports" - - "prettier-plugin-solidity" -printWidth: 120 -proseWrap: "always" -singleQuote: false -tabWidth: 2 -trailingComma: "all" - -overrides: - - files: "*.sol" - options: - compiler: "0.8.24" - parser: "solidity-parse" - tabWidth: 4 - - files: "*.ts" - options: - importOrder: ["", "^[./]"] - importOrderParserPlugins: ["typescript"] - importOrderSeparation: true - importOrderSortSpecifiers: true - parser: "typescript" diff --git a/contracts/.solcover.js b/contracts/.solcover.js deleted file mode 100644 index 938b911..0000000 --- a/contracts/.solcover.js +++ /dev/null @@ -1,11 +0,0 @@ -module.exports = { - istanbulReporter: ["html", "lcov"], - providerOptions: { - mnemonic: process.env.MNEMONIC, - }, - skipFiles: ["test", "fhevmTemp"], - mocha: { - fgrep: "[skip-on-coverage]", - invert: true, - }, -}; diff --git a/contracts/.solhint.json b/contracts/.solhint.json deleted file mode 100644 index 826fe4e..0000000 --- a/contracts/.solhint.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "extends": "solhint:recommended", - "plugins": ["prettier"], - "rules": { - "const-name-snakecase": "off", - "no-global-import": "off", - "reason-string": "off", - "state-visibility": "off", - "custom-errors": "off", - "code-complexity": ["error", 8], - "compiler-version": ["error", ">=0.8.4"], - "func-visibility": ["error", { "ignoreConstructors": true }], - "max-line-length": ["error", 120], - "named-parameters-mapping": "off", - "no-console": "off", - "not-rely-on-time": "off", - "prettier/prettier": [ - "error", - { - "endOfLine": "auto" - } - ] - } -} diff --git a/contracts/.solhintignore b/contracts/.solhintignore deleted file mode 100644 index 16dc0c0..0000000 --- a/contracts/.solhintignore +++ /dev/null @@ -1,3 +0,0 @@ -# directories -**/artifacts -**/node_modules diff --git a/contracts/CustomProvider.ts b/contracts/CustomProvider.ts deleted file mode 100644 index c4fb241..0000000 --- a/contracts/CustomProvider.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { ethers } from "ethers"; -import { ProviderWrapper } from "hardhat/plugins"; -import type { EIP1193Provider, RequestArguments } from "hardhat/types"; - -interface Test { - request: EIP1193Provider["request"]; -} - -class CustomProvider extends ProviderWrapper implements Test { - public lastBlockSnapshot: number; - public lastCounterRand: number; - public lastBlockSnapshotForDecrypt: number; - - constructor(protected readonly _wrappedProvider: EIP1193Provider) { - super(_wrappedProvider); - this.lastBlockSnapshot = 0; // Initialize the variable - this.lastCounterRand = 0; - this.lastBlockSnapshotForDecrypt = 0; - } - - async request(args: RequestArguments): ReturnType { - if (args.method === "evm_revert") { - const result = await this._wrappedProvider.request(args); - const blockNumberHex = (await this._wrappedProvider.request({ method: "eth_blockNumber" })) as string; - this.lastBlockSnapshot = parseInt(blockNumberHex); - this.lastBlockSnapshotForDecrypt = parseInt(blockNumberHex); - - const callData = { - to: "0x000000000000000000000000000000000000005d", - data: "0x1f20d85c", - }; - this.lastCounterRand = (await this._wrappedProvider.request({ - method: "eth_call", - params: [callData, "latest"], - })) as number; - return result; - } - if (args.method === "get_lastBlockSnapshot") { - return [this.lastBlockSnapshot, this.lastCounterRand]; - } - if (args.method === "get_lastBlockSnapshotForDecrypt") { - return this.lastBlockSnapshotForDecrypt; - } - if (args.method === "set_lastBlockSnapshot") { - this.lastBlockSnapshot = Array.isArray(args.params!) && args.params[0]; - return this.lastBlockSnapshot; - } - if (args.method === "set_lastBlockSnapshotForDecrypt") { - this.lastBlockSnapshotForDecrypt = Array.isArray(args.params!) && args.params[0]; - return this.lastBlockSnapshotForDecrypt; - } - const result = this._wrappedProvider.request(args); - return result; - } -} - -export default CustomProvider; diff --git a/contracts/LICENSE.md b/contracts/LICENSE.md deleted file mode 100644 index 88a2b87..0000000 --- a/contracts/LICENSE.md +++ /dev/null @@ -1,16 +0,0 @@ -MIT License - -Copyright (c) 2023 Paul Razvan Berg - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the Software without restriction, including without limitation the -rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit -persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the -Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE -WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR -OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/contracts/README.md b/contracts/README.md deleted file mode 100644 index 8308819..0000000 --- a/contracts/README.md +++ /dev/null @@ -1,189 +0,0 @@ -# Hardhat Template [![Open in Gitpod][gitpod-badge]][gitpod] [![Github Actions][gha-badge]][gha] [![Hardhat][hardhat-badge]][hardhat] [![License: MIT][license-badge]][license] - -[gitpod]: https://gitpod.io/#https://github.com/zama-ai/fhevm-hardhat-template -[gitpod-badge]: https://img.shields.io/badge/Gitpod-Open%20in%20Gitpod-FFB45B?logo=gitpod -[gha]: https://github.com/zama-ai/fhevm-hardhat-template/actions -[gha-badge]: https://github.com/zama-ai/fhevm-hardhat-template/actions/workflows/ci.yml/badge.svg -[hardhat]: https://hardhat.org/ -[hardhat-badge]: https://img.shields.io/badge/Built%20with-Hardhat-FFDB1C.svg -[license]: https://opensource.org/licenses/MIT -[license-badge]: https://img.shields.io/badge/License-MIT-blue.svg - -A Hardhat-based template for developing Solidity smart contracts, with sensible defaults. - -- [Hardhat](https://github.com/nomiclabs/hardhat): compile, run and test smart contracts -- [TypeChain](https://github.com/ethereum-ts/TypeChain): generate TypeScript bindings for smart contracts -- [Ethers](https://github.com/ethers-io/ethers.js/): renowned Ethereum library and wallet implementation -- [Solhint](https://github.com/protofire/solhint): code linter -- [Solcover](https://github.com/sc-forks/solidity-coverage): code coverage -- [Prettier Plugin Solidity](https://github.com/prettier-solidity/prettier-plugin-solidity): code formatter - -## Getting Started - -Click the [`Use this template`](https://github.com/zama-ai/fhevm-hardhat-template/generate) button at the top of the -page to create a new repository with this repo as the initial state. - -## Features - -This template builds upon the frameworks and libraries mentioned above, so for details about their specific features, -please consult their respective documentations. - -For example, for Hardhat, you can refer to the [Hardhat Tutorial](https://hardhat.org/tutorial) and the -[Hardhat Docs](https://hardhat.org/docs). You might be in particular interested in reading the -[Testing Contracts](https://hardhat.org/tutorial/testing-contracts) section. - -### Sensible Defaults - -This template comes with sensible default configurations in the following files: - -```text -├── .editorconfig -├── .eslintignore -├── .eslintrc.yml -├── .gitignore -├── .prettierignore -├── .prettierrc.yml -├── .solcover.js -├── .solhint.json -└── hardhat.config.ts -``` - -### VSCode Integration - -This template is IDE agnostic, but for the best user experience, you may want to use it in VSCode alongside Nomic -Foundation's [Solidity extension](https://marketplace.visualstudio.com/items?itemName=NomicFoundation.hardhat-solidity). - -### GitHub Actions - -This template comes with GitHub Actions pre-configured. Your contracts will be linted and tested on every push and pull -request made to the `main` branch. - -Note though that to make this work, you must use your `INFURA_API_KEY` and your `MNEMONIC` as GitHub secrets. - -You can edit the CI script in [.github/workflows/ci.yml](./.github/workflows/ci.yml). - -## Usage - -### Pre Requisites - -Install [pnpm](https://pnpm.io/installation) - -Before being able to run any command, you need to create a `.env` file and set a BIP-39 compatible mnemonic as the `MNEMONIC` -environment variable. You can follow the example in `.env.example` or start with the following command: - -```sh -cp .env.example .env -``` - -If you don't already have a mnemonic, you can use this [website](https://iancoleman.io/bip39/) to generate one. An alternative, if you have [foundry](https://book.getfoundry.sh/getting-started/installation) installed is to use the `cast wallet new-mnemonic` command. - -Then, install all needed dependencies - please **_make sure to use Node v20_** or more recent: - -```sh -pnpm install -``` - -### Compile - -Compile the smart contracts with Hardhat: - -```sh -pnpm compile -``` - -### TypeChain - -Compile the smart contracts and generate TypeChain bindings: - -```sh -pnpm typechain -``` - -### Test - -Run the tests with Hardhat - this will run the tests on a local hardhat node in mocked mode (i.e the FHE operations and decryptions will be simulated by default): - -```sh -pnpm test -``` - -### Lint Solidity - -Lint the Solidity code: - -```sh -pnpm lint:sol -``` - -### Lint TypeScript - -Lint the TypeScript code: - -```sh -pnpm lint:ts -``` - - -### Clean - -Delete the smart contract artifacts, the coverage reports and the Hardhat cache: - -```sh -pnpm clean -``` - -### Mocked mode - -The mocked mode allows faster testing and the ability to analyze coverage of the tests. In this mocked version, -encrypted types are not really encrypted, and the tests are run on the original version of the EVM, on a local hardhat -network instance. To run the tests in mocked mode, you can use directly the following command: - -```bash -pnpm test -``` - -You can still use all the usual specific [hardhat network methods](https://hardhat.org/hardhat-network/docs/reference#hardhat-network-methods), such as `evm_snapshot`, `evm_mine`, `evm_increaseTime`, etc, which are very helpful in a testing context. Another useful hardhat feature, is the [console.log](https://hardhat.org/hardhat-network/docs/reference#console.log) function which can be used in fhevm smart contracts in mocked mode as well. - -To analyze the coverage of the tests (in mocked mode necessarily, as this cannot be done on the real fhEVM node), you -can use this command : - -```bash -pnpm coverage -``` - -Then open the file `coverage/index.html`. You can see there which line or branch for each contract which has been -covered or missed by your test suite. This allows increased security by pointing out missing branches not covered yet by -the current tests. - -Finally, a new fhevm-specific feature is available in mocked mode: the `debug.decrypt[XX]` functions, which can decrypt directly any encrypted value. Please refer to the [utils.ts](https://github.com/zama-ai/fhevm/blob/main/test/utils.ts#L87-L317) file for the corresponding documentation. - -> [!Note] -> Due to intrinsic limitations of the original EVM, the mocked version differs in rare edge cases from the real fhEVM, the main difference is the gas consumption for the FHE operations (native gas is around 20% underestimated in mocked mode). This means that before deploying to production, developers should still run the tests with the original fhEVM node, as a final check - i.e in non-mocked mode (see next section). - -### Non-mocked mode - Sepolia - -To run your test on a real fhevm node, you can use the coprocessor deployed on the Sepolia test network. To do this, ensure you are using a valid value `SEPOLIA_RPC_URL` in your `.env` file. You can get free Sepolia RPC URLs by creating an account on services such as [Infura](https://www.infura.io/) or [Alchemy](https://www.alchemy.com/). Then you should use the following command: - -```bash -npx hardhat test [PATH_TO_YOUR_TEST] --network sepolia -``` - -The `--network sepolia` flag will make your test run on a real fhevm coprocessor. Obviously, for the same tests to pass on Sepolia, contrarily to mocked mode, you are not allowed to use any hardhat node specific method, and neither use any of the `debug.decrypt[XX]` functions. - -> [!Note] -> For this test to succeed, first ensure you set your own private `MNEMONIC` variable in the `.env` file and then ensure you have funded your test accounts on Sepolia. For example you can use the following command to get the corresponding private keys associated with the first `5` accounts derived from the mnemonic: -``` -npx hardhat get-accounts --num-accounts 5 -``` -This will let you add them to the Metamask app, to easily fund them from your personal wallet. - -If you don't own already Sepolia test tokens, you can for example use a free faucet such as [https://sepolia-faucet.pk910.de/](https://sepolia-faucet.pk910.de/). - -### Syntax Highlighting - -If you use VSCode, you can get Solidity syntax highlighting with the -[hardhat-solidity](https://marketplace.visualstudio.com/items?itemName=NomicFoundation.hardhat-solidity) extension. - -## License - -This project is licensed under MIT. diff --git a/contracts/contracts/MyConfidentialERC20.sol b/contracts/contracts/MyConfidentialERC20.sol deleted file mode 100644 index 3faf6fa..0000000 --- a/contracts/contracts/MyConfidentialERC20.sol +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause-Clear - -pragma solidity ^0.8.24; - -import "fhevm/lib/TFHE.sol"; -import "fhevm/config/ZamaFHEVMConfig.sol"; -import "fhevm-contracts/contracts/token/ERC20/extensions/ConfidentialERC20Mintable.sol"; - -/// @notice This contract implements an encrypted ERC20-like token with confidential balances using Zama's FHE library. -/// @dev It supports typical ERC20 functionality such as transferring tokens, minting, and setting allowances, -/// @dev but uses encrypted data types. -contract MyConfidentialERC20 is SepoliaZamaFHEVMConfig, ConfidentialERC20Mintable { - /// @notice Constructor to initialize the token's name and symbol, and set up the owner - /// @param name_ The name of the token - /// @param symbol_ The symbol of the token - constructor(string memory name_, string memory symbol_) ConfidentialERC20Mintable(name_, symbol_, msg.sender) {} -} diff --git a/contracts/contracts/TestAsyncDecrypt.sol b/contracts/contracts/TestAsyncDecrypt.sol deleted file mode 100644 index 0a5e6e9..0000000 --- a/contracts/contracts/TestAsyncDecrypt.sol +++ /dev/null @@ -1,549 +0,0 @@ -// SPDX-License-Identifier: BSD-3-Clause-Clear - -pragma solidity ^0.8.24; - -import "fhevm/lib/TFHE.sol"; -import "fhevm/config/ZamaFHEVMConfig.sol"; -import "fhevm/config/ZamaGatewayConfig.sol"; -import "fhevm/gateway/GatewayCaller.sol"; - -/// @notice Contract for testing asynchronous decryption using the Gateway -contract TestAsyncDecrypt is SepoliaZamaFHEVMConfig, SepoliaZamaGatewayConfig, GatewayCaller { - /// @dev Encrypted state variables - ebool xBool; - euint4 xUint4; - euint8 xUint8; - euint16 xUint16; - euint32 xUint32; - euint64 xUint64; - euint64 xUint64_2; - euint64 xUint64_3; - euint128 xUint128; - eaddress xAddress; - eaddress xAddress2; - euint256 xUint256; - - /// @dev Decrypted state variables - bool public yBool; - uint8 public yUint4; - uint8 public yUint8; - uint16 public yUint16; - uint32 public yUint32; - uint64 public yUint64; - uint64 public yUint64_2; - uint64 public yUint64_3; - uint128 public yUint128; - address public yAddress; - address public yAddress2; - uint256 public yUint256; - bytes public yBytes64; - bytes public yBytes128; - bytes public yBytes256; - - /// @dev Tracks the latest decryption request ID - uint256 public latestRequestID; - - /// @notice Constructor to initialize the contract and set up encrypted values - constructor() { - /// @dev Initialize encrypted variables with sample values - xBool = TFHE.asEbool(true); - TFHE.allowThis(xBool); - xUint4 = TFHE.asEuint4(4); - TFHE.allowThis(xUint4); - xUint8 = TFHE.asEuint8(42); - TFHE.allowThis(xUint8); - xUint16 = TFHE.asEuint16(16); - TFHE.allowThis(xUint16); - xUint32 = TFHE.asEuint32(32); - TFHE.allowThis(xUint32); - xUint64 = TFHE.asEuint64(18446744073709551600); - TFHE.allowThis(xUint64); - xUint64_2 = TFHE.asEuint64(76575465786); - TFHE.allowThis(xUint64_2); - xUint64_3 = TFHE.asEuint64(6400); - TFHE.allowThis(xUint64_3); - xUint128 = TFHE.asEuint128(1267650600228229401496703205443); - TFHE.allowThis(xUint128); - xUint256 = TFHE.asEuint256(27606985387162255149739023449108101809804435888681546220650096895197251); - TFHE.allowThis(xUint256); - xAddress = TFHE.asEaddress(0x8ba1f109551bD432803012645Ac136ddd64DBA72); - TFHE.allowThis(xAddress); - xAddress2 = TFHE.asEaddress(0xf48b8840387ba3809DAE990c930F3b4766A86ca3); - TFHE.allowThis(xAddress2); - } - - /// @notice Function to request decryption with an excessive delay (should revert) - function requestBoolAboveDelay() public { - /// @dev This should revert due to the excessive delay - uint256[] memory cts = new uint256[](1); - cts[0] = Gateway.toUint256(xBool); - Gateway.requestDecryption(cts, this.callbackBool.selector, 0, block.timestamp + 2 days, false); - } - - /// @notice Request decryption of a boolean value - function requestBool() public { - uint256[] memory cts = new uint256[](1); - cts[0] = Gateway.toUint256(xBool); - /// @dev Request decryption with a 100-second deadline and non-trustless mode - Gateway.requestDecryption(cts, this.callbackBool.selector, 0, block.timestamp + 100, false); - } - - /// @notice Request decryption of a boolean value in trustless mode - function requestBoolTrustless() public { - uint256[] memory cts = new uint256[](1); - cts[0] = Gateway.toUint256(xBool); - /// @dev Request decryption with a 100-second deadline and trustless mode (true) - uint256 requestID = Gateway.requestDecryption( - cts, - this.callbackBoolTrustless.selector, - 0, - block.timestamp + 100, - true - ); - latestRequestID = requestID; - /// @dev Save the requested handles for later verification - saveRequestedHandles(requestID, cts); - } - - /// @notice Callback function for non-trustless boolean decryption - function callbackBool(uint256, bool decryptedInput) public onlyGateway returns (bool) { - yBool = decryptedInput; - return yBool; - } - - /// @notice Callback function for trustless boolean decryption - function callbackBoolTrustless( - uint256 requestID, - bool decryptedInput, - bytes[] memory signatures - ) public onlyGateway returns (bool) { - /// @dev Verify that the requestID matches the latest request - require(latestRequestID == requestID, "wrong requestID passed by Gateway"); - /// @dev Load the previously saved handles for verification - uint256[] memory requestedHandles = loadRequestedHandles(latestRequestID); - /// @dev Verify the signatures provided by the KMS (Key Management Service) - bool isKMSVerified = Gateway.verifySignatures(requestedHandles, signatures); - require(isKMSVerified, "KMS did not verify this decryption result"); - /// @dev If verification passes, store the decrypted value - yBool = decryptedInput; - return yBool; - } - - /// @notice Request decryption of a 4-bit unsigned integer - function requestUint4() public { - uint256[] memory cts = new uint256[](1); - cts[0] = Gateway.toUint256(xUint4); - Gateway.requestDecryption(cts, this.callbackUint4.selector, 0, block.timestamp + 100, false); - } - - /// @notice Callback function for 4-bit unsigned integer decryption - /// @param decryptedInput The decrypted 4-bit unsigned integer - /// @return The decrypted value - function callbackUint4(uint256, uint8 decryptedInput) public onlyGateway returns (uint8) { - yUint4 = decryptedInput; - return decryptedInput; - } - - /// @notice Request decryption of an 8-bit unsigned integer - function requestUint8() public { - uint256[] memory cts = new uint256[](1); - cts[0] = Gateway.toUint256(xUint8); - Gateway.requestDecryption(cts, this.callbackUint8.selector, 0, block.timestamp + 100, false); - } - - /// @notice Callback function for 8-bit unsigned integer decryption - /// @param decryptedInput The decrypted 8-bit unsigned integer - /// @return The decrypted value - function callbackUint8(uint256, uint8 decryptedInput) public onlyGateway returns (uint8) { - yUint8 = decryptedInput; - return decryptedInput; - } - - /// @notice Request decryption of a 16-bit unsigned integer - function requestUint16() public { - uint256[] memory cts = new uint256[](1); - cts[0] = Gateway.toUint256(xUint16); - Gateway.requestDecryption(cts, this.callbackUint16.selector, 0, block.timestamp + 100, false); - } - - /// @notice Callback function for 16-bit unsigned integer decryption - /// @param decryptedInput The decrypted 16-bit unsigned integer - /// @return The decrypted value - function callbackUint16(uint256, uint16 decryptedInput) public onlyGateway returns (uint16) { - yUint16 = decryptedInput; - return decryptedInput; - } - - /// @notice Request decryption of a 32-bit unsigned integer with additional inputs - /// @param input1 First additional input - /// @param input2 Second additional input - function requestUint32(uint32 input1, uint32 input2) public { - uint256[] memory cts = new uint256[](1); - cts[0] = Gateway.toUint256(xUint32); - uint256 requestID = Gateway.requestDecryption( - cts, - this.callbackUint32.selector, - 0, - block.timestamp + 100, - false - ); - addParamsUint256(requestID, input1); - addParamsUint256(requestID, input2); - } - - /// @notice Callback function for 32-bit unsigned integer decryption - /// @param requestID The ID of the decryption request - /// @param decryptedInput The decrypted 32-bit unsigned integer - /// @return The result of the computation - function callbackUint32(uint256 requestID, uint32 decryptedInput) public onlyGateway returns (uint32) { - uint256[] memory params = getParamsUint256(requestID); - unchecked { - uint32 result = uint32(params[0]) + uint32(params[1]) + decryptedInput; - yUint32 = result; - return result; - } - } - - /// @notice Request decryption of a 64-bit unsigned integer - function requestUint64() public { - uint256[] memory cts = new uint256[](1); - cts[0] = Gateway.toUint256(xUint64); - Gateway.requestDecryption(cts, this.callbackUint64.selector, 0, block.timestamp + 100, false); - } - - /// @notice Request decryption of a non-trivial 64-bit unsigned integer - /// @param inputHandle The input handle for the encrypted value - /// @param inputProof The input proof for the encrypted value - function requestUint64NonTrivial(einput inputHandle, bytes calldata inputProof) public { - euint64 inputNonTrivial = TFHE.asEuint64(inputHandle, inputProof); - uint256[] memory cts = new uint256[](1); - cts[0] = Gateway.toUint256(inputNonTrivial); - Gateway.requestDecryption(cts, this.callbackUint64.selector, 0, block.timestamp + 100, false); - } - - /// @notice Callback function for 64-bit unsigned integer decryption - /// @param decryptedInput The decrypted 64-bit unsigned integer - /// @return The decrypted value - function callbackUint64(uint256, uint64 decryptedInput) public onlyGateway returns (uint64) { - yUint64 = decryptedInput; - return decryptedInput; - } - - function requestUint128() public { - uint256[] memory cts = new uint256[](1); - cts[0] = Gateway.toUint256(xUint128); - Gateway.requestDecryption(cts, this.callbackUint128.selector, 0, block.timestamp + 100, false); - } - - function requestUint128NonTrivial(einput inputHandle, bytes calldata inputProof) public { - euint128 inputNonTrivial = TFHE.asEuint128(inputHandle, inputProof); - uint256[] memory cts = new uint256[](1); - cts[0] = Gateway.toUint256(inputNonTrivial); - Gateway.requestDecryption(cts, this.callbackUint128.selector, 0, block.timestamp + 100, false); - } - - function callbackUint128(uint256, uint128 decryptedInput) public onlyGateway returns (uint128) { - yUint128 = decryptedInput; - return decryptedInput; - } - - function requestUint256() public { - uint256[] memory cts = new uint256[](1); - cts[0] = Gateway.toUint256(xUint256); - Gateway.requestDecryption(cts, this.callbackUint256.selector, 0, block.timestamp + 100, false); - } - - function requestUint256NonTrivial(einput inputHandle, bytes calldata inputProof) public { - euint256 inputNonTrivial = TFHE.asEuint256(inputHandle, inputProof); - uint256[] memory cts = new uint256[](1); - cts[0] = Gateway.toUint256(inputNonTrivial); - Gateway.requestDecryption(cts, this.callbackUint256.selector, 0, block.timestamp + 100, false); - } - - function callbackUint256(uint256, uint256 decryptedInput) public onlyGateway returns (uint256) { - yUint256 = decryptedInput; - return decryptedInput; - } - - function requestEbytes64NonTrivial(einput inputHandle, bytes calldata inputProof) public { - ebytes64 inputNonTrivial = TFHE.asEbytes64(inputHandle, inputProof); - uint256[] memory cts = new uint256[](1); - cts[0] = Gateway.toUint256(inputNonTrivial); - Gateway.requestDecryption(cts, this.callbackBytes64.selector, 0, block.timestamp + 100, false); - } - - function requestEbytes64Trivial(bytes calldata value) public { - ebytes64 inputTrivial = TFHE.asEbytes64(TFHE.padToBytes64(value)); - uint256[] memory cts = new uint256[](1); - cts[0] = Gateway.toUint256(inputTrivial); - Gateway.requestDecryption(cts, this.callbackBytes64.selector, 0, block.timestamp + 100, false); - } - - function callbackBytes64(uint256, bytes calldata decryptedInput) public onlyGateway returns (bytes memory) { - yBytes64 = decryptedInput; - return decryptedInput; - } - - function requestEbytes128NonTrivial(einput inputHandle, bytes calldata inputProof) public { - ebytes128 inputNonTrivial = TFHE.asEbytes128(inputHandle, inputProof); - uint256[] memory cts = new uint256[](1); - cts[0] = Gateway.toUint256(inputNonTrivial); - Gateway.requestDecryption(cts, this.callbackBytes128.selector, 0, block.timestamp + 100, false); - } - - function requestEbytes128Trivial(bytes calldata value) public { - ebytes128 inputTrivial = TFHE.asEbytes128(TFHE.padToBytes128(value)); - uint256[] memory cts = new uint256[](1); - cts[0] = Gateway.toUint256(inputTrivial); - Gateway.requestDecryption(cts, this.callbackBytes128.selector, 0, block.timestamp + 100, false); - } - - function callbackBytes128(uint256, bytes calldata decryptedInput) public onlyGateway returns (bytes memory) { - yBytes128 = decryptedInput; - return decryptedInput; - } - - function requestEbytes256Trivial(bytes calldata value) public { - ebytes256 inputTrivial = TFHE.asEbytes256(TFHE.padToBytes256(value)); - uint256[] memory cts = new uint256[](1); - cts[0] = Gateway.toUint256(inputTrivial); - Gateway.requestDecryption(cts, this.callbackBytes256.selector, 0, block.timestamp + 100, false); - } - - function requestEbytes256NonTrivial(einput inputHandle, bytes calldata inputProof) public { - ebytes256 inputNonTrivial = TFHE.asEbytes256(inputHandle, inputProof); - uint256[] memory cts = new uint256[](1); - cts[0] = Gateway.toUint256(inputNonTrivial); - Gateway.requestDecryption(cts, this.callbackBytes256.selector, 0, block.timestamp + 100, false); - } - - /// @notice Callback function for 256-bit encrypted bytes decryption - /// @param decryptedInput The decrypted 256-bit bytes - /// @return The decrypted value - function callbackBytes256(uint256, bytes calldata decryptedInput) public onlyGateway returns (bytes memory) { - yBytes256 = decryptedInput; - return decryptedInput; - } - - /// @notice Request decryption of an encrypted address - function requestAddress() public { - uint256[] memory cts = new uint256[](1); - cts[0] = Gateway.toUint256(xAddress); - Gateway.requestDecryption(cts, this.callbackAddress.selector, 0, block.timestamp + 100, false); - } - - /// @notice Request decryption of multiple encrypted addresses - function requestSeveralAddresses() public { - uint256[] memory cts = new uint256[](2); - cts[0] = Gateway.toUint256(xAddress); - cts[1] = Gateway.toUint256(xAddress2); - Gateway.requestDecryption(cts, this.callbackAddresses.selector, 0, block.timestamp + 100, false); - } - - /// @notice Callback function for multiple address decryption - /// @param decryptedInput1 The first decrypted address - /// @param decryptedInput2 The second decrypted address - /// @return The first decrypted address - function callbackAddresses( - uint256 /*requestID*/, - address decryptedInput1, - address decryptedInput2 - ) public onlyGateway returns (address) { - yAddress = decryptedInput1; - yAddress2 = decryptedInput2; - return decryptedInput1; - } - - /// @notice Callback function for address decryption - /// @param decryptedInput The decrypted address - /// @return The decrypted address - function callbackAddress(uint256, address decryptedInput) public onlyGateway returns (address) { - yAddress = decryptedInput; - return decryptedInput; - } - - /// @notice Request decryption of multiple encrypted data types - /// @dev This function demonstrates how to request decryption for various encrypted data types in a single call - /// @param input1 First additional input parameter for the callback function - /// @param input2 Second additional input parameter for the callback function - function requestMixed(uint32 input1, uint32 input2) public { - uint256[] memory cts = new uint256[](10); - cts[0] = Gateway.toUint256(xBool); - cts[1] = Gateway.toUint256(xBool); - cts[2] = Gateway.toUint256(xUint4); - cts[3] = Gateway.toUint256(xUint8); - cts[4] = Gateway.toUint256(xUint16); - cts[5] = Gateway.toUint256(xUint32); - cts[6] = Gateway.toUint256(xUint64); - cts[7] = Gateway.toUint256(xUint64); - cts[8] = Gateway.toUint256(xUint64); - cts[9] = Gateway.toUint256(xAddress); - uint256 requestID = Gateway.requestDecryption( - cts, - this.callbackMixed.selector, - 0, - block.timestamp + 100, - false - ); - addParamsUint256(requestID, input1); - addParamsUint256(requestID, input2); - } - - /// @notice Callback function for mixed data type decryption - /// @dev Processes the decrypted values and performs some basic checks - /// @param requestID The ID of the decryption request - /// @param decBool_1 First decrypted boolean - /// @param decBool_2 Second decrypted boolean - /// @param decUint4 Decrypted 4-bit unsigned integer - /// @param decUint8 Decrypted 8-bit unsigned integer - /// @param decUint16 Decrypted 16-bit unsigned integer - /// @param decUint32 Decrypted 32-bit unsigned integer - /// @param decUint64_1 First decrypted 64-bit unsigned integer - /// @param decUint64_2 Second decrypted 64-bit unsigned integer - /// @param decUint64_3 Third decrypted 64-bit unsigned integer - /// @param decAddress Decrypted address - /// @return The decrypted 4-bit unsigned integer - function callbackMixed( - uint256 requestID, - bool decBool_1, - bool decBool_2, - uint8 decUint4, - uint8 decUint8, - uint16 decUint16, - uint32 decUint32, - uint64 decUint64_1, - uint64 decUint64_2, - uint64 decUint64_3, - address decAddress - ) public onlyGateway returns (uint8) { - yBool = decBool_1; - require(decBool_1 == decBool_2, "Wrong decryption"); - yUint4 = decUint4; - yUint8 = decUint8; - yUint16 = decUint16; - uint256[] memory params = getParamsUint256(requestID); - unchecked { - uint32 result = uint32(params[0]) + uint32(params[1]) + decUint32; - yUint32 = result; - } - yUint64 = decUint64_1; - require(decUint64_1 == decUint64_2 && decUint64_2 == decUint64_3, "Wrong decryption"); - yAddress = decAddress; - return yUint4; - } - - /// @notice Request decryption of mixed data types including 256-bit encrypted bytes - /// @dev Demonstrates how to include encrypted bytes256 in a mixed decryption request - /// @param inputHandle The encrypted input handle for the bytes256 - /// @param inputProof The proof for the encrypted bytes256 - function requestMixedBytes256(einput inputHandle, bytes calldata inputProof) public { - ebytes256 xBytes256 = TFHE.asEbytes256(inputHandle, inputProof); - uint256[] memory cts = new uint256[](4); - cts[0] = Gateway.toUint256(xBool); - cts[1] = Gateway.toUint256(xAddress); - cts[2] = Gateway.toUint256(xBytes256); - ebytes64 input64Bytes = TFHE.asEbytes64(TFHE.padToBytes64(hex"aaff42")); - cts[3] = Gateway.toUint256(input64Bytes); - Gateway.requestDecryption(cts, this.callbackMixedBytes256.selector, 0, block.timestamp + 100, false); - } - - /// @notice Callback function for mixed data type decryption including 256-bit encrypted bytes - /// @dev Processes and stores the decrypted values - /// @param decBool Decrypted boolean - /// @param decAddress Decrypted address - /// @param bytesRes Decrypted 256-bit bytes - function callbackMixedBytes256( - uint256, - bool decBool, - address decAddress, - bytes memory bytesRes, - bytes memory bytesRes2 - ) public onlyGateway { - yBool = decBool; - yAddress = decAddress; - yBytes256 = bytesRes; - yBytes64 = bytesRes2; - } - - /// @notice Request trustless decryption of non-trivial 256-bit encrypted bytes - /// @dev Demonstrates how to request trustless decryption for complex encrypted bytes256 - /// @param inputHandle The encrypted input handle for the bytes256 - /// @param inputProof The proof for the encrypted bytes256 - function requestEbytes256NonTrivialTrustless(einput inputHandle, bytes calldata inputProof) public { - ebytes256 inputNonTrivial = TFHE.asEbytes256(inputHandle, inputProof); - uint256[] memory cts = new uint256[](1); - cts[0] = Gateway.toUint256(inputNonTrivial); - uint256 requestID = Gateway.requestDecryption( - cts, - this.callbackBytes256Trustless.selector, - 0, - block.timestamp + 100, - true - ); - latestRequestID = requestID; - saveRequestedHandles(requestID, cts); - } - - /// @notice Callback function for trustless decryption of 256-bit encrypted bytes - /// @dev Verifies the decryption result using KMS signatures - /// @param requestID The ID of the decryption request - /// @param decryptedInput The decrypted bytes256 value - /// @param signatures The signatures from the KMS for verification - /// @return The decrypted bytes256 value - function callbackBytes256Trustless( - uint256 requestID, - bytes calldata decryptedInput, - bytes[] memory signatures - ) public onlyGateway returns (bytes memory) { - require(latestRequestID == requestID, "wrong requestID passed by Gateway"); - uint256[] memory requestedHandles = loadRequestedHandles(latestRequestID); - bool isKMSVerified = Gateway.verifySignatures(requestedHandles, signatures); - require(isKMSVerified, "KMS did not verify this decryption result"); - yBytes256 = decryptedInput; - return decryptedInput; - } - - /// @notice Request trustless decryption of mixed data types including 256-bit encrypted bytes - /// @dev Demonstrates how to request trustless decryption for multiple data types - /// @param inputHandle The encrypted input handle for the bytes256 - /// @param inputProof The proof for the encrypted bytes256 - function requestMixedBytes256Trustless(einput inputHandle, bytes calldata inputProof) public { - ebytes256 xBytes256 = TFHE.asEbytes256(inputHandle, inputProof); - uint256[] memory cts = new uint256[](3); - cts[0] = Gateway.toUint256(xBool); - cts[1] = Gateway.toUint256(xBytes256); - cts[2] = Gateway.toUint256(xAddress); - uint256 requestID = Gateway.requestDecryption( - cts, - this.callbackMixedBytes256Trustless.selector, - 0, - block.timestamp + 100, - true - ); - latestRequestID = requestID; - saveRequestedHandles(requestID, cts); - } - - /// @notice Callback function for trustless decryption of mixed data types including 256-bit encrypted bytes - /// @dev Verifies and processes the decrypted values - /// @param requestID The ID of the decryption request - /// @param decBool Decrypted boolean - /// @param bytesRes Decrypted 256-bit bytes - /// @param decAddress Decrypted address - /// @param signatures The signatures from the KMS for verification - function callbackMixedBytes256Trustless( - uint256 requestID, - bool decBool, - bytes memory bytesRes, - address decAddress, - bytes[] memory signatures - ) public onlyGateway { - require(latestRequestID == requestID, "wrong requestID passed by Gateway"); - uint256[] memory requestedHandles = loadRequestedHandles(latestRequestID); - bool isKMSVerified = Gateway.verifySignatures(requestedHandles, signatures); - require(isKMSVerified, "KMS did not verify this decryption result"); - yBool = decBool; - yAddress = decAddress; - yBytes256 = bytesRes; - } -} diff --git a/contracts/contracts/confidentialCounter/sample1.sol b/contracts/contracts/confidentialCounter/sample1.sol deleted file mode 100644 index 2730e78..0000000 --- a/contracts/contracts/confidentialCounter/sample1.sol +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; - -import "fhevm/lib/TFHE.sol"; -import "fhevm/config/ZamaFHEVMConfig.sol"; - -/// @title EncryptedCounter1 -/// @notice A basic contract demonstrating the setup of encrypted types -/// @dev Uses TFHE library for fully homomorphic encryption operations -/// @custom:experimental This is a minimal example contract intended only for learning purposes -/// @custom:notice This contract has limited real-world utility and serves primarily as a starting point -/// for understanding how to implement basic FHE operations in Solidity -contract EncryptedCounter1 is SepoliaZamaFHEVMConfig { - euint8 internal counter; - euint8 internal immutable CONST_ONE; - - constructor() { - // Initialize counter with an encrypted zero value - counter = TFHE.asEuint8(0); - TFHE.allowThis(counter); - // Save on gas by computing the constant here - CONST_ONE = TFHE.asEuint8(1); - TFHE.allowThis(CONST_ONE); - } - - function increment() public { - // Perform encrypted addition to increment the counter - counter = TFHE.add(counter, CONST_ONE); - TFHE.allowThis(counter); - } -} diff --git a/contracts/contracts/confidentialCounter/sample2.sol b/contracts/contracts/confidentialCounter/sample2.sol deleted file mode 100644 index d6efd9f..0000000 --- a/contracts/contracts/confidentialCounter/sample2.sol +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; - -import "fhevm/lib/TFHE.sol"; -import "fhevm/config/ZamaFHEVMConfig.sol"; - -/// @title EncryptedCounter2 -/// @notice A contract that maintains an encrypted counter and is meant for demonstrating how to add encrypted types -/// @dev Uses TFHE library for fully homomorphic encryption operations -/// @custom:experimental This contract is experimental and uses FHE technology -contract EncryptedCounter2 is SepoliaZamaFHEVMConfig { - euint8 counter; - - constructor() { - // Initialize counter with an encrypted zero value - counter = TFHE.asEuint8(0); - TFHE.allowThis(counter); - } - - function incrementBy(einput amount, bytes calldata inputProof) public { - // Convert input to euint8 and add to counter - euint8 incrementAmount = TFHE.asEuint8(amount, inputProof); - counter = TFHE.add(counter, incrementAmount); - TFHE.allowThis(counter); - } -} diff --git a/contracts/contracts/confidentialCounter/sample3.sol b/contracts/contracts/confidentialCounter/sample3.sol deleted file mode 100644 index 3f4708e..0000000 --- a/contracts/contracts/confidentialCounter/sample3.sol +++ /dev/null @@ -1,51 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; - -import "fhevm/lib/TFHE.sol"; -import "fhevm/config/ZamaFHEVMConfig.sol"; -import "fhevm/config/ZamaGatewayConfig.sol"; -import "fhevm/gateway/GatewayCaller.sol"; - -/// @title EncryptedCounter3 -/// @notice A contract that maintains an encrypted counter and is meant for demonstrating how decryption works -/// @dev Uses TFHE library for fully homomorphic encryption operations and Gateway for decryption -/// @custom:experimental This contract is experimental and uses FHE technology with decryption capabilities -contract EncryptedCounter3 is SepoliaZamaFHEVMConfig, SepoliaZamaGatewayConfig, GatewayCaller { - /// @dev Decrypted state variable - euint8 counter; - uint8 public decryptedCounter; - - constructor() { - // Initialize counter with an encrypted zero value - counter = TFHE.asEuint8(0); - TFHE.allowThis(counter); - } - - function incrementBy(einput amount, bytes calldata inputProof) public { - // Convert input to euint8 and add to counter - euint8 incrementAmount = TFHE.asEuint8(amount, inputProof); - counter = TFHE.add(counter, incrementAmount); - TFHE.allowThis(counter); - } - - /// @notice Request decryption of the counter value - function requestDecryptCounter() public { - uint256[] memory cts = new uint256[](1); - cts[0] = Gateway.toUint256(counter); - Gateway.requestDecryption(cts, this.callbackCounter.selector, 0, block.timestamp + 100, false); - } - - /// @notice Callback function for counter decryption - /// @param decryptedInput The decrypted counter value - /// @return The decrypted value - function callbackCounter(uint256, uint8 decryptedInput) public onlyGateway returns (uint8) { - decryptedCounter = decryptedInput; - return decryptedInput; - } - - /// @notice Get the decrypted counter value - /// @return The decrypted counter value - function getDecryptedCounter() public view returns (uint8) { - return decryptedCounter; - } -} diff --git a/contracts/contracts/confidentialCounter/sample4.sol b/contracts/contracts/confidentialCounter/sample4.sol deleted file mode 100644 index bcd08f8..0000000 --- a/contracts/contracts/confidentialCounter/sample4.sol +++ /dev/null @@ -1,31 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; - -import "fhevm/lib/TFHE.sol"; -import "fhevm/config/ZamaFHEVMConfig.sol"; - -/// @title EncryptedCounter4 -/// @notice A contract that maintains encrypted counters for each user and is meant for demonstrating how re-encryption works -/// @dev Uses TFHE library for fully homomorphic encryption operations -/// @custom:security Each user can only access and modify their own counter -/// @custom:experimental This contract is experimental and uses FHE technology -contract EncryptedCounter4 is SepoliaZamaFHEVMConfig { - // Mapping from user address to their encrypted counter value - mapping(address => euint8) private counters; - - function incrementBy(einput amount, bytes calldata inputProof) public { - // Initialize counter if it doesn't exist - counters[msg.sender] = TFHE.asEuint8(0); - - // Convert input to euint8 and add to sender's counter - euint8 incrementAmount = TFHE.asEuint8(amount, inputProof); - counters[msg.sender] = TFHE.add(counters[msg.sender], incrementAmount); - TFHE.allowThis(counters[msg.sender]); - TFHE.allow(counters[msg.sender], msg.sender); - } - - function getCounter() public view returns (euint8) { - // Return the encrypted counter value for the sender - return counters[msg.sender]; - } -} diff --git a/contracts/contracts/decIdentity/Diploma.sol b/contracts/contracts/decIdentity/Diploma.sol deleted file mode 100644 index a7fc29d..0000000 --- a/contracts/contracts/decIdentity/Diploma.sol +++ /dev/null @@ -1,214 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import "fhevm/lib/TFHE.sol"; -import "./IdMapping.sol"; -import "@openzeppelin/contracts/access/AccessControl.sol"; -import "fhevm/config/ZamaFHEVMConfig.sol"; - -/** - * @title Diploma - * @author ZAMA - * @dev Contract for managing encrypted diploma records using TFHE encryption - * @notice Allows universities to register encrypted diploma data and graduates to generate claims - */ -contract Diploma is SepoliaZamaFHEVMConfig, AccessControl { - /// @dev Constants - bytes32 public constant REGISTRAR_ROLE = keccak256("REGISTRAR_ROLE"); - bytes32 public constant OWNER_ROLE = keccak256("OWNER_ROLE"); - - /// @dev Custom errors - /// @notice Thrown when attempting to register a diploma for a user who already has one - error DiplomaAlreadyRegistered(); - /// @notice Thrown when attempting to access diploma data for a user who doesn't have one registered - error DiplomaNotRegistered(); - /// @notice Thrown when sender doesn't have permission to access the encrypted data - error AccessNotPermitted(); - /// @notice Thrown when claim generation fails, includes failure data - /// @param data The error data returned from the failed claim generation - error ClaimGenerationFailed(bytes data); - - /// @dev Structure to hold encrypted diploma data - struct DiplomaData { - euint64 id; // Encrypted unique diploma ID - ebytes64 university; // Encrypted university identifier - euint16 degree; // Encrypted degree identifier - ebytes64 grade; // Encrypted grade - } - - /// @dev Instance of IdMapping contract - IdMapping private idMapping; - - /// @dev Mapping to store diploma records by user ID - mapping(uint256 => DiplomaData) private diplomaRecords; - /// @dev Mapping to track registered diplomas - mapping(uint256 => bool) public registered; - /// @dev Mapping for degree identifiers to degree names - mapping(uint16 => string) public degreeTypes; - - /// @dev Event emitted when a diploma is registered - event DiplomaRegistered(address indexed graduate); - /// @dev Event emitted when a claim is generated - event ClaimGenerated(address indexed graduate, address claimAddress, string claimFn); - - /** - * @dev Constructor to initialize the contract with IdMapping address - * @param _idMappingAddress Address of the IdMapping contract - */ - constructor(address _idMappingAddress) { - idMapping = IdMapping(_idMappingAddress); - _grantRole(OWNER_ROLE, msg.sender); // Admin role for contract owner - _grantRole(REGISTRAR_ROLE, msg.sender); // Registrar role for contract owner - - // Initialize degree mappings - degreeTypes[1] = "Electrical Engineering (B.Eng)"; - degreeTypes[2] = "Mechanical Engineering (B.Eng)"; - degreeTypes[3] = "Computer Science (B.Sc)"; - degreeTypes[4] = "Civil Engineering (B.Eng)"; - degreeTypes[5] = "Chemical Engineering (B.Eng)"; - // Graduate degrees start from 1001 - degreeTypes[1001] = "Electrical Engineering (M.Eng)"; - degreeTypes[1002] = "Mechanical Engineering (M.Eng)"; - degreeTypes[1003] = "Computer Science (M.Sc)"; - // Doctoral degrees start from 2001 - degreeTypes[2001] = "Electrical Engineering (Ph.D)"; - degreeTypes[2002] = "Computer Science (Ph.D)"; - } - - /** - * @dev Adds a new registrar address - * @param registrar Address to be granted registrar role - */ - function addRegistrar(address registrar) external onlyRole(OWNER_ROLE) { - _grantRole(REGISTRAR_ROLE, registrar); - } - - /** - * @dev Removes a registrar address - * @param registrar Address to be revoked registrar role - */ - function removeRegistrar(address registrar) external onlyRole(OWNER_ROLE) { - _revokeRole(REGISTRAR_ROLE, registrar); - } - - /** - * @dev Retrieves the degree type for a given degree ID - * @param degreeId The ID of the degree type to retrieve - * @return The name/description of the degree type - */ - function getDegreeType(uint16 degreeId) public view returns (string memory) { - return degreeTypes[degreeId]; - } - - /** - * @dev Registers a new encrypted diploma for a user - * @param userId ID of the user to register diploma for - * @param university Encrypted university identifier - * @param degree Encrypted degree type - * @param grade Encrypted grade - * @param inputProof Proof for encrypted inputs - * @return bool indicating success - */ - function registerDiploma( - uint256 userId, - einput university, - einput degree, - einput grade, - bytes calldata inputProof - ) public virtual onlyRole(REGISTRAR_ROLE) returns (bool) { - if (registered[userId]) revert DiplomaAlreadyRegistered(); - - // Generate a new encrypted diploma ID - euint64 newId = TFHE.randEuint64(); - - // Store the encrypted diploma data - diplomaRecords[userId] = DiplomaData({ - id: newId, - university: TFHE.asEbytes64(university, inputProof), - degree: TFHE.asEuint16(degree, inputProof), - grade: TFHE.asEbytes64(grade, inputProof) - }); - - registered[userId] = true; // Mark the diploma as registered - - // Get the address associated with the user ID - address addressToBeAllowed = idMapping.getAddr(userId); - - // Allow the graduate to access their own data - TFHE.allow(diplomaRecords[userId].id, addressToBeAllowed); - TFHE.allow(diplomaRecords[userId].university, addressToBeAllowed); - TFHE.allow(diplomaRecords[userId].degree, addressToBeAllowed); - TFHE.allow(diplomaRecords[userId].grade, addressToBeAllowed); - - // Allow the contract to access the data - TFHE.allowThis(diplomaRecords[userId].id); - TFHE.allowThis(diplomaRecords[userId].university); - TFHE.allowThis(diplomaRecords[userId].degree); - TFHE.allowThis(diplomaRecords[userId].grade); - - emit DiplomaRegistered(addressToBeAllowed); // Emit event for diploma registration - - return true; - } - - /** - * @dev Retrieves encrypted university identifier for a user - * @param userId ID of the user to get university for - * @return euint8 Encrypted university identifier - */ - function getMyUniversity(uint256 userId) public view virtual returns (ebytes64) { - if (!registered[userId]) revert DiplomaNotRegistered(); - return diplomaRecords[userId].university; - } - - /** - * @dev Retrieves encrypted degree type for a user - * @param userId ID of the user to get degree for - * @return euint8 Encrypted degree type - */ - function getMyDegree(uint256 userId) public view virtual returns (euint16) { - if (!registered[userId]) revert DiplomaNotRegistered(); - return diplomaRecords[userId].degree; - } - - /** - * @dev Retrieves encrypted grade for a user - * @param userId ID of the user to get grade for - * @return euint8 Encrypted grade - */ - function getMyGrade(uint256 userId) public view virtual returns (ebytes64) { - if (!registered[userId]) revert DiplomaNotRegistered(); - return diplomaRecords[userId].grade; - } - - /** - * @dev Checks if a diploma is registered for a user - * @param userId ID of the user to check - * @return bool indicating if diploma exists - */ - function hasDiploma(uint256 userId) public view virtual returns (bool) { - return registered[userId]; - } - - /** - * @dev Generates a claim for a diploma - * @param claimAddress Address of the claim contract - * @param claimFn Function signature to call on claim contract - */ - function generateClaim(address claimAddress, string memory claimFn) public { - /// @dev Only the msg.sender that is registered under the user ID can make the claim - uint256 userId = idMapping.getId(msg.sender); - - /// @dev Grant temporary access for graduate's data to be used in claim generation - TFHE.allowTransient(diplomaRecords[userId].degree, claimAddress); - - /// @dev Ensure the sender can access this graduate's data - if (!TFHE.isSenderAllowed(diplomaRecords[userId].degree)) revert AccessNotPermitted(); - - /// @dev Attempt the external call and capture the result - (bool success, bytes memory data) = claimAddress.call(abi.encodeWithSignature(claimFn, userId)); - if (!success) revert ClaimGenerationFailed(data); - - emit ClaimGenerated(msg.sender, claimAddress, claimFn); /// @dev Emit event for claim generation - } -} diff --git a/contracts/contracts/decIdentity/EmployerClaim.sol b/contracts/contracts/decIdentity/EmployerClaim.sol deleted file mode 100644 index 56d41fd..0000000 --- a/contracts/contracts/decIdentity/EmployerClaim.sol +++ /dev/null @@ -1,207 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import "fhevm/lib/TFHE.sol"; -import "./PassportID.sol"; -import "./Diploma.sol"; -import "@openzeppelin/contracts/access/Ownable2Step.sol"; -import "fhevm/config/ZamaFHEVMConfig.sol"; - -/** - * @title EmployerClaim - * @author ZAMA - * @dev Contract for managing encrypted claims about users' age and education credentials - * @notice Allows generation and verification of encrypted claims for employment verification - */ -contract EmployerClaim is SepoliaZamaFHEVMConfig, Ownable2Step { - /// @dev Age threshold timestamp for adult verification (Jan 1, 2006 - 18 years on Jan 1, 2024) - uint64 private constant AGE_THRESHOLD_TIMESTAMP = 1136070000; - /// @dev Required degree level for education verification (Computer Science (B.Sc)) - uint16 private constant REQUIRED_DEGREE_LEVEL = 3; - /// @dev Constant representing an invalid claim ID - uint256 private constant INVALID_CLAIM = 0; - euint64 private _AGE_THRESHOLD; - euint16 private _REQUIRED_DEGREE; - - /// @dev Error thrown when an invalid claim ID is provided - error InvalidClaimId(); - /// @dev Error thrown when an invalid contract address is provided - error InvalidContractAddress(); - /// @dev Error thrown when caller is not authorized - error NotAuthorized(); - - /// @dev Counter for tracking the latest claim ID - uint64 public lastClaimId = 0; - /// @dev Mapping of claim IDs to encrypted boolean results for adult claims - mapping(uint64 => ebool) private adultClaims; - /// @dev Mapping of claim IDs to encrypted boolean results for degree claims - mapping(uint64 => ebool) private degreeClaims; - /// @dev Mapping of user IDs to encrypted boolean results for verified claims - mapping(uint256 => ebool) private verifiedClaims; - - /// @dev Emitted when an adult claim is generated - /// @param claimId The ID of the generated claim - /// @param userId The ID of the user the claim is for - event AdultClaimGenerated(uint64 claimId, uint256 userId); - /// @dev Emitted when a degree claim is generated - /// @param claimId The ID of the generated claim - /// @param userId The ID of the user the claim is for - event DegreeClaimGenerated(uint64 claimId, uint256 userId); - - /// @dev Instance of IdMapping contract for user ID management - IdMapping private idMapping; - /// @dev Instance of PassportID contract for identity verification - PassportID private passportContract; - /// @dev Instance of Diploma contract for education verification - Diploma private diplomaContract; - - /** - * @dev Constructor to initialize the contract with required contract addresses - * @param _idMappingAddress Address of the IdMapping contract - * @param _passportAddress Address of the PassportID contract - * @param _diplomaAddress Address of the Diploma contract - * @custom:throws InvalidContractAddress if any address is zero - */ - constructor(address _idMappingAddress, address _passportAddress, address _diplomaAddress) Ownable(msg.sender) { - if (_idMappingAddress == address(0) || _passportAddress == address(0) || _diplomaAddress == address(0)) - revert InvalidContractAddress(); - - idMapping = IdMapping(_idMappingAddress); - passportContract = PassportID(_passportAddress); - diplomaContract = Diploma(_diplomaAddress); - - /// Set age threshold to 18 years (in Unix timestamp) - _AGE_THRESHOLD = TFHE.asEuint64(AGE_THRESHOLD_TIMESTAMP); - - /// Use constant for required degree - _REQUIRED_DEGREE = TFHE.asEuint16(REQUIRED_DEGREE_LEVEL); - - TFHE.allowThis(_AGE_THRESHOLD); - TFHE.allowThis(_REQUIRED_DEGREE); - } - - /** - * @dev Generates an encrypted claim verifying if a user is above 18 years old - * @param userId The ID of the user to generate the claim for - * @return The ID of the generated claim - * @custom:throws NotAuthorized if caller is not the passport contract - * @custom:emits AdultClaimGenerated when claim is generated - */ - function generateAdultClaim(uint256 userId) public returns (uint64) { - if (msg.sender != address(passportContract)) revert NotAuthorized(); - - /// Retrieve the address associated with the user ID - address addressToBeAllowed = idMapping.getAddr(userId); - - /// Retrieve the user's encrypted birthdate from the PassportID contract - euint64 birthdate = passportContract.getBirthdate(userId); - - lastClaimId++; - - /// Check if birthdate indicates user is over 18 - ebool isAdult = TFHE.le(birthdate, _AGE_THRESHOLD); - - /// Store the result of the claim - adultClaims[lastClaimId] = isAdult; - - /// Grant access to the claim to both the contract and user for verification purposes - TFHE.allowThis(isAdult); - TFHE.allow(isAdult, addressToBeAllowed); - - /// Emit an event for the generated claim - emit AdultClaimGenerated(lastClaimId, userId); - - return lastClaimId; - } - - /** - * @dev Retrieves the result of an adult claim - * @param claimId The ID of the claim to retrieve - * @return The encrypted boolean result of the claim - * @custom:throws InvalidClaimId if claim ID is invalid - */ - function getAdultClaim(uint64 claimId) public view returns (ebool) { - if (claimId == 0 || claimId > lastClaimId) revert InvalidClaimId(); - return adultClaims[claimId]; - } - - /** - * @dev Generates an encrypted claim verifying if a user has required degree credentials - * @param userId The ID of the user to generate the claim for - * @return The ID of the generated claim - * @custom:throws NotAuthorized if caller is not the diploma contract - * @custom:emits DegreeClaimGenerated when claim is generated - */ - function generateDegreeClaim(uint256 userId) public returns (uint64) { - if (msg.sender != address(diplomaContract)) revert NotAuthorized(); - - /// Retrieve the address associated with the user ID - address addressToBeAllowed = idMapping.getAddr(userId); - - /// Get the diploma data from the Diploma contract - euint16 userUniversity = diplomaContract.getMyDegree(userId); - - lastClaimId++; - - /// Check if university and degree match requirements - ebool degreeMatch = TFHE.eq(userUniversity, _REQUIRED_DEGREE); - - /// Store the result of the claim - degreeClaims[lastClaimId] = degreeMatch; - - /// Grant access to the claim - TFHE.allowThis(degreeMatch); - TFHE.allow(degreeMatch, addressToBeAllowed); - - /// Emit an event for the generated claim - emit DegreeClaimGenerated(lastClaimId, userId); - - return lastClaimId; - } - - /** - * @dev Retrieves the result of a degree claim - * @param claimId The ID of the claim to retrieve - * @return The encrypted boolean result of the claim - * @custom:throws InvalidClaimId if claim ID is invalid - */ - function getDegreeClaim(uint64 claimId) public view returns (ebool) { - if (claimId == 0 || claimId > lastClaimId) revert InvalidClaimId(); - return degreeClaims[claimId]; - } - - /** - * @dev Verifies both adult and degree claims for a user - * @param userId The ID of the user to verify claims for - * @param adultClaim The ID of the adult claim to verify - * @param degreeClaim The ID of the degree claim to verify - * @custom:throws InvalidClaimId if either claim ID is invalid - * @notice This function combines adult and degree claims into a single verification - */ - function verifyClaims(uint256 userId, uint64 adultClaim, uint64 degreeClaim) public { - if (adultClaim == INVALID_CLAIM || adultClaim > lastClaimId) revert InvalidClaimId(); - if (degreeClaim == INVALID_CLAIM || degreeClaim > lastClaimId) revert InvalidClaimId(); - - ebool isAdult = adultClaims[adultClaim]; - ebool degreeMatch = degreeClaims[degreeClaim]; - - ebool verify = TFHE.and(isAdult, degreeMatch); - - /// Store the verification result under the userId mapping - verifiedClaims[userId] = verify; - - /// Grant access to the claim - TFHE.allowThis(verify); - TFHE.allow(verify, owner()); - } - - /** - * @dev Retrieves the result of a verified claim for a user - * @param userId The ID of the user to get the verified claim for - * @return The encrypted boolean result of the verified claim - * @notice Returns the combined verification status of adult and degree claims - */ - function getVerifyClaim(uint256 userId) public view returns (ebool) { - return verifiedClaims[userId]; - } -} diff --git a/contracts/contracts/decIdentity/IdMapping.sol b/contracts/contracts/decIdentity/IdMapping.sol deleted file mode 100644 index 4d28ea4..0000000 --- a/contracts/contracts/decIdentity/IdMapping.sol +++ /dev/null @@ -1,114 +0,0 @@ -/// SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; - -import "@openzeppelin/contracts/access/Ownable2Step.sol"; -import "fhevm/config/ZamaFHEVMConfig.sol"; - -/** - * @title IdMapping - * @author ZAMA - * @notice Manages unique ID mappings between addresses and sequential IDs - * @dev Inherits from Ownable2Step for secure ownership transfer - */ -contract IdMapping is SepoliaZamaFHEVMConfig, Ownable2Step { - /// Custom errors - /// @notice Thrown when attempting to generate an ID for an address that already has one - error IdAlreadyGenerated(); - /// @notice Thrown when attempting to use the zero address - error InvalidAddress(); - /// @notice Thrown when the maximum ID value has been reached - error IdOverflow(); - /// @notice Thrown when trying to look up an ID for an address that hasn't generated one - error NoIdGenerated(); - /// @notice Thrown when attempting to use an ID that doesn't exist - error InvalidId(); - /// @notice Thrown when no address is found for a given ID - error NoAddressFound(); - - /// @notice Maps user addresses to their unique IDs - mapping(address => uint256) public addressToId; - /// @dev Maps unique IDs back to user addresses - mapping(uint256 => address) private idToAddress; - /// @dev Counter for assigning sequential IDs, starts at 1 - uint256 private nextId = 1; - - /** - * @notice Emitted when a new ID is generated for a user - * @param user The address of the user receiving the ID - * @param id The unique ID assigned to the user - */ - event IdGenerated(address indexed user, uint256 indexed id); - - /** - * @notice Initializes the contract with the deployer as owner - * @dev Sets initial ID counter to 1 - */ - constructor() Ownable(msg.sender) { - nextId = 1; - } - - /** - * @notice Generates a unique ID for the calling address - * @dev Each address can only generate one ID. IDs are assigned sequentially starting from 1 - * @return uint256 The newly generated ID - * @custom:throws IdAlreadyGenerated if caller already has an ID - * @custom:throws InvalidAddress if caller is zero address - * @custom:throws IdOverflow if maximum ID value is reached - */ - function generateId() public returns (uint256) { - if (addressToId[msg.sender] != 0) revert IdAlreadyGenerated(); - if (msg.sender == address(0)) revert InvalidAddress(); - - uint256 newId = nextId; - - addressToId[msg.sender] = newId; - idToAddress[newId] = msg.sender; - nextId++; - - emit IdGenerated(msg.sender, newId); - return newId; - } - - /** - * @notice Looks up the ID associated with a given address - * @dev Reverts if address has no ID or is zero address - * @param _addr The address to lookup - * @return uint256 The ID associated with the address - * @custom:throws InvalidAddress if provided address is zero address - * @custom:throws NoIdGenerated if address has no ID assigned - */ - function getId(address _addr) public view returns (uint256) { - if (_addr == address(0)) revert InvalidAddress(); - if (addressToId[_addr] == 0) revert NoIdGenerated(); - return addressToId[_addr]; - } - - /** - * @notice Looks up the address associated with a given ID - * @dev Reverts if ID is invalid or has no associated address - * @param _id The ID to lookup - * @return address The address associated with the ID - * @custom:throws InvalidId if ID is 0 or greater than the last assigned ID - * @custom:throws NoAddressFound if no address is associated with the ID - */ - function getAddr(uint256 _id) public view returns (address) { - if (_id <= 0 || _id >= nextId) revert InvalidId(); - address addr = idToAddress[_id]; - if (addr == address(0)) revert NoAddressFound(); - return addr; - } - - /** - * @notice Removes an address's ID mapping - * @dev Only callable by contract owner. Removes both address->ID and ID->address mappings - * @param _addr The address whose ID mapping should be reset - * @custom:throws NoIdGenerated if address has no ID assigned - */ - function resetIdForAddress(address _addr) external onlyOwner { - uint256 id = addressToId[_addr]; - if (id == 0) revert NoIdGenerated(); - - delete addressToId[_addr]; - delete idToAddress[id]; - } -} diff --git a/contracts/contracts/decIdentity/PassportID.sol b/contracts/contracts/decIdentity/PassportID.sol deleted file mode 100644 index a717e85..0000000 --- a/contracts/contracts/decIdentity/PassportID.sol +++ /dev/null @@ -1,243 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import "fhevm/lib/TFHE.sol"; -import "./IdMapping.sol"; -import "@openzeppelin/contracts/access/AccessControl.sol"; -import "fhevm/config/ZamaFHEVMConfig.sol"; - -/** - * @title PassportID - * @author ZAMA - * @notice Manages encrypted passport identity data and verification claims - * @dev Implements role-based access control for registrars and admins to manage identity registration - */ -contract PassportID is SepoliaZamaFHEVMConfig, AccessControl { - /// @dev Constants - bytes32 public constant REGISTRAR_ROLE = keccak256("REGISTRAR_ROLE"); - bytes32 public constant OWNER_ROLE = keccak256("OWNER_ROLE"); - - /// @dev Custom errors - /// @notice Thrown when attempting to register an identity for a user who already has one - error AlreadyRegistered(); - /// @notice Thrown when attempting to access identity data for a user who doesn't have one registered - error IdentityNotRegistered(); - /// @notice Thrown when sender doesn't have permission to access the encrypted data - error AccessNotPermitted(); - /// @notice Thrown when claim generation fails, includes failure data - /// @param data The error data returned from the failed claim generation - error ClaimGenerationFailed(bytes data); - error InvalidField(); - - /** - * @dev Structure to hold encrypted identity data - * @param id Encrypted unique identifier for the identity record - * @param biodata Encrypted biometric data like fingerprints or facial data - * @param firstname Encrypted legal first name from passport - * @param lastname Encrypted legal last name from passport - * @param birthdate Encrypted date of birth in unix timestamp format - */ - struct Identity { - euint64 id; /// @dev Encrypted unique ID - ebytes64 biodata; /// @dev Encrypted biodata (e.g., biometric data or hashed identity data) - ebytes64 firstname; /// @dev Encrypted first name - ebytes64 lastname; /// @dev Encrypted last name - euint64 birthdate; /// @dev Encrypted birthdate for age verification - } - - /// @dev Instance of IdMapping contract - IdMapping private idMapping; - - /// @dev Mapping to store identities by user ID - mapping(uint256 => Identity) private citizenIdentities; - /// @dev Mapping to track registered identities - mapping(uint256 => bool) public registered; - - /// @dev Event emitted when an identity is registered - event IdentityRegistered(address indexed user); - - /** - * @notice Initializes the passport identity management system - * @dev Sets up FHEVM config and grants admin/registrar roles to deployer - * @param _idMappingAddress Address of the IdMapping contract for user ID management - */ - constructor(address _idMappingAddress) { - idMapping = IdMapping(_idMappingAddress); - _grantRole(OWNER_ROLE, msg.sender); /// @dev Admin role for contract owner - _grantRole(REGISTRAR_ROLE, msg.sender); /// @dev Registrar role for contract owner - } - - /** - * @notice Grants registrar privileges to a new address - * @dev Only callable by admin role - * @param registrar Address to be granted registrar permissions - */ - function addRegistrar(address registrar) external onlyRole(OWNER_ROLE) { - _grantRole(REGISTRAR_ROLE, registrar); - } - - /** - * @notice Revokes registrar privileges from an address - * @dev Only callable by admin role - * @param registrar Address to have registrar permissions revoked - */ - function removeRegistrar(address registrar) external onlyRole(OWNER_ROLE) { - _revokeRole(REGISTRAR_ROLE, registrar); - } - - /** - * @notice Creates a new encrypted identity record - * @dev Only admin role can register new identities. All data is stored in encrypted form - * @param userId Unique identifier for the user from IdMapping contract - * @param biodata Encrypted biometric/identity data with proof - * @param firstname Encrypted first name with proof - * @param lastname Encrypted last name with proof - * @param birthdate Encrypted birthdate with proof - * @param inputProof Zero-knowledge proof validating the encrypted inputs - * @return bool True if registration was successful - * @custom:throws AlreadyRegistered if userId already has an identity registered - */ - function registerIdentity( - uint256 userId, - einput biodata, - einput firstname, - einput lastname, - einput birthdate, - bytes calldata inputProof - ) public virtual onlyRole(REGISTRAR_ROLE) returns (bool) { - if (registered[userId]) revert AlreadyRegistered(); - - /// @dev Generate a new encrypted unique ID - euint64 newId = TFHE.randEuint64(); - - /// @dev Store the encrypted identity data - citizenIdentities[userId] = Identity({ - id: newId, - biodata: TFHE.asEbytes64(biodata, inputProof), - firstname: TFHE.asEbytes64(firstname, inputProof), - lastname: TFHE.asEbytes64(lastname, inputProof), - birthdate: TFHE.asEuint64(birthdate, inputProof) - }); - - registered[userId] = true; /// @dev Mark the identity as registered - - /// @dev Get the address associated with the user ID - address addressToBeAllowed = idMapping.getAddr(userId); - - /// @dev Allow the user to access their own data - TFHE.allow(citizenIdentities[userId].id, addressToBeAllowed); - TFHE.allow(citizenIdentities[userId].biodata, addressToBeAllowed); - TFHE.allow(citizenIdentities[userId].firstname, addressToBeAllowed); - TFHE.allow(citizenIdentities[userId].lastname, addressToBeAllowed); - TFHE.allow(citizenIdentities[userId].birthdate, addressToBeAllowed); - - /// @dev Allow the contract to access the data - TFHE.allowThis(citizenIdentities[userId].id); - TFHE.allowThis(citizenIdentities[userId].biodata); - TFHE.allowThis(citizenIdentities[userId].firstname); - TFHE.allowThis(citizenIdentities[userId].lastname); - TFHE.allowThis(citizenIdentities[userId].birthdate); - - emit IdentityRegistered(addressToBeAllowed); /// @dev Emit event for identity registration - - return true; - } - - /** - * @notice Retrieves the complete encrypted identity record for a user - * @dev Returns all encrypted identity fields as a tuple - * @param userId ID of the user whose identity to retrieve - * @return Tuple containing (id, biodata, firstname, lastname, birthdate) - * @custom:throws IdentityNotRegistered if no identity exists for userId - */ - function getIdentity(uint256 userId) public view virtual returns (euint64, ebytes64, ebytes64, ebytes64, euint64) { - if (!registered[userId]) revert IdentityNotRegistered(); - return ( - citizenIdentities[userId].id, - citizenIdentities[userId].biodata, - citizenIdentities[userId].firstname, - citizenIdentities[userId].lastname, - citizenIdentities[userId].birthdate - ); - } - - /** - * @notice Retrieves only the encrypted birthdate for a user - * @dev Useful for age verification claims - * @param userId ID of the user whose birthdate to retrieve - * @return Encrypted birthdate as euint64 - * @custom:throws IdentityNotRegistered if no identity exists for userId - */ - function getBirthdate(uint256 userId) public view virtual returns (euint64) { - if (!registered[userId]) revert IdentityNotRegistered(); - return citizenIdentities[userId].birthdate; - } - - /** - * @notice Retrieves only the encrypted first name for a user - * @dev Useful for identity verification claims - * @param userId ID of the user whose first name to retrieve - * @return Encrypted first name as euint8 - * @custom:throws IdentityNotRegistered if no identity exists for userId - */ - function getMyIdentityFirstname(uint256 userId) public view virtual returns (ebytes64) { - if (!registered[userId]) revert IdentityNotRegistered(); - return citizenIdentities[userId].firstname; - } - - /** - * @notice Generates a verification claim using the user's identity data - * @dev Temporarily grants claim contract access to required encrypted data - * @param claimAddress Contract address that will process the claim - * @param claimFn Function signature in the claim contract to call - * @custom:throws AccessNotPermitted if sender lacks permission to access data - * @custom:throws ClaimGenerationFailed if external claim call fails - */ - function generateClaim(address claimAddress, string memory claimFn) public { - /// @dev Only the msg.sender that is registered under the user ID can make the claim - uint256 userId = idMapping.getId(msg.sender); - - /// @dev Grant temporary access for citizen's birthdate to be used in claim generation - TFHE.allowTransient(citizenIdentities[userId].birthdate, claimAddress); - - /// @dev Ensure the sender can access this citizen's birthdate - if (!TFHE.isSenderAllowed(citizenIdentities[userId].birthdate)) revert AccessNotPermitted(); - - /// @dev Attempt the external call and capture the result - (bool success, bytes memory data) = claimAddress.call(abi.encodeWithSignature(claimFn, userId)); - if (!success) revert ClaimGenerationFailed(data); - } - - /** - * @notice Generates a verification claim using the user's identity data - * @dev Temporarily grants claim contract access to required encrypted data - * @param claimAddress Contract address that will process the claim - * @param claimFn Function signature in the claim contract to call - * @custom:throws AccessNotPermitted if sender lacks permission to access data - * @custom:throws ClaimGenerationFailed if external claim call fails - */ - function generateClaim(address claimAddress, string memory claimFn, string[] memory fields) public { - /// @dev Only the msg.sender that is registered under the user ID can make the claim - uint256 userId = idMapping.getId(msg.sender); - - /// @dev Grant temporary access for each requested field - for (uint i = 0; i < fields.length; i++) { - if (bytes(fields[i]).length == 0) revert InvalidField(); - - if (keccak256(bytes(fields[i])) == keccak256(bytes("id"))) { - TFHE.allowTransient(citizenIdentities[userId].id, claimAddress); - /// @dev Ensure the sender can access this citizen's university - if (!TFHE.isSenderAllowed(citizenIdentities[userId].id)) revert AccessNotPermitted(); - } else if (keccak256(bytes(fields[i])) == keccak256(bytes("birthdate"))) { - TFHE.allowTransient(citizenIdentities[userId].birthdate, claimAddress); - if (!TFHE.isSenderAllowed(citizenIdentities[userId].birthdate)) revert AccessNotPermitted(); - } else { - revert InvalidField(); - } - } - - /// @dev Attempt the external call and capture the result - (bool success, bytes memory data) = claimAddress.call(abi.encodeWithSignature(claimFn, userId)); - if (!success) revert ClaimGenerationFailed(data); - } -} diff --git a/contracts/deploy/deploy.ts b/contracts/deploy/deploy.ts deleted file mode 100644 index ab33ec0..0000000 --- a/contracts/deploy/deploy.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { DeployFunction } from "hardhat-deploy/types"; -import { HardhatRuntimeEnvironment } from "hardhat/types"; - -const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { - const { deployer } = await hre.getNamedAccounts(); - const { deploy } = hre.deployments; - - // Deploy MyConfidentialERC20 - const deployedERC20 = await deploy("MyConfidentialERC20", { - from: deployer, - args: ["Naraggara", "NARA"], - log: true, - }); - console.log(`MyConfidentialERC20 contract: `, deployedERC20.address); - - // Deploy EncryptedCounter4 - const deployedCounter = await deploy("EncryptedCounter4", { - from: deployer, - args: [], // No constructor arguments needed - log: true, - }); - console.log(`EncryptedCounter4 contract: `, deployedCounter.address); -}; - -export default func; -func.id = "deploy_confidentialERC20"; // id required to prevent reexecution -func.tags = ["MyConfidentialERC20"]; diff --git a/contracts/eslint.config.mjs b/contracts/eslint.config.mjs deleted file mode 100644 index 03e3173..0000000 --- a/contracts/eslint.config.mjs +++ /dev/null @@ -1,17 +0,0 @@ -import eslint from "@eslint/js"; -import globals from "globals"; -import tseslint from "typescript-eslint"; - -export default [ - { - languageOptions: { - globals: globals.node, - }, - linterOptions: { - reportUnusedDisableDirectives: "off", - }, - ignores: ["abi/", "artifacts/", "cache/", "res/", "types/*"], - }, - eslint.configs.recommended, - ...tseslint.configs.recommended, -]; diff --git a/contracts/hardhat.config.ts b/contracts/hardhat.config.ts deleted file mode 100644 index 2769e77..0000000 --- a/contracts/hardhat.config.ts +++ /dev/null @@ -1,150 +0,0 @@ -import "@nomicfoundation/hardhat-toolbox"; -import "@openzeppelin/hardhat-upgrades"; -import dotenv from "dotenv"; -import "hardhat-deploy"; -import "hardhat-ignore-warnings"; -import { HardhatUserConfig, extendProvider } from "hardhat/config"; -import { task } from "hardhat/config"; -import type { NetworkUserConfig } from "hardhat/types"; -import { resolve } from "path"; - -import CustomProvider from "./CustomProvider"; -// Adjust the import path as needed -import "./tasks/accounts"; -import "./tasks/mint"; -import { setCodeMocked } from "./test/mockedSetup"; - -extendProvider(async (provider) => { - const newProvider = new CustomProvider(provider); - return newProvider; -}); - -task("compile:specific", "Compiles only the specified contract") - .addParam("contract", "The contract's path") - .setAction(async ({ contract }, hre) => { - // Adjust the configuration to include only the specified contract - hre.config.paths.sources = contract; - - await hre.run("compile"); - }); - -const dotenvConfigPath: string = process.env.DOTENV_CONFIG_PATH || "./.env"; -dotenv.config({ path: resolve(__dirname, dotenvConfigPath) }); - -// Ensure that we have all the environment variables we need. -const mnemonic: string = process.env.MNEMONIC!; - -const chainIds = { - zama: 8009, - local: 9000, - localCoprocessor: 12345, - sepolia: 11155111, -}; - -function getChainConfig(chain: keyof typeof chainIds): NetworkUserConfig { - let jsonRpcUrl: string; - switch (chain) { - case "local": - jsonRpcUrl = "http://localhost:8545"; - break; - case "localCoprocessor": - jsonRpcUrl = "http://localhost:8745"; - break; - case "zama": - jsonRpcUrl = "https://devnet.zama.ai"; - break; - case "sepolia": - jsonRpcUrl = process.env.SEPOLIA_RPC_URL!; - } - return { - accounts: { - count: 10, - mnemonic, - path: "m/44'/60'/0'/0", - }, - chainId: chainIds[chain], - url: jsonRpcUrl, - }; -} - -task("coverage").setAction(async (taskArgs, hre, runSuper) => { - hre.config.networks.hardhat.allowUnlimitedContractSize = true; - hre.config.networks.hardhat.blockGasLimit = 1099511627775; - - await runSuper(taskArgs); -}); - -task("test", async (taskArgs, hre, runSuper) => { - // Run modified test task - if (hre.network.name === "hardhat") { - await setCodeMocked(hre); - } - await runSuper(); -}); - -const config: HardhatUserConfig = { - defaultNetwork: "hardhat", - namedAccounts: { - deployer: 0, - }, - mocha: { - timeout: 500000, - }, - gasReporter: { - currency: "USD", - enabled: process.env.REPORT_GAS ? true : false, - excludeContracts: [], - src: "./contracts", - }, - networks: { - hardhat: { - accounts: { - count: 10, - mnemonic, - path: "m/44'/60'/0'/0", - }, - }, - sepolia: getChainConfig("sepolia"), - zama: getChainConfig("zama"), - localDev: getChainConfig("local"), - local: getChainConfig("local"), - localCoprocessor: getChainConfig("localCoprocessor"), - }, - paths: { - artifacts: "./artifacts", - cache: "./cache", - sources: "./contracts", - tests: "./test", - }, - solidity: { - version: "0.8.24", - settings: { - metadata: { - // Not including the metadata hash - // https://github.com/paulrberg/hardhat-template/issues/31 - bytecodeHash: "none", - }, - // Disable the optimizer when debugging - // https://hardhat.org/hardhat-network/#solidity-optimizer-support - optimizer: { - enabled: true, - runs: 800, - }, - evmVersion: "cancun", - }, - }, - etherscan: { - apiKey: process.env.ETHERSCAN_API_KEY!, - }, - warnings: { - "*": { - "transient-storage": false, - }, - }, - typechain: { - outDir: "types", - target: "ethers-v6", - }, -}; - -export default config; diff --git a/contracts/package.json b/contracts/package.json deleted file mode 100644 index fafe312..0000000 --- a/contracts/package.json +++ /dev/null @@ -1,100 +0,0 @@ -{ - "name": "@zama-ai/fhevm-hardhat-template", - "description": "fhEVM hardhat template", - "version": "1.0.0", - "engines": { - "node": ">=20.0.0" - }, - "author": { - "name": "zama-ai", - "url": "https://github.com/zama-ai" - }, - "devDependencies": { - "@eslint/js": "^9.9.0", - "@nomicfoundation/hardhat-chai-matchers": "^2.0.0", - "@nomicfoundation/hardhat-ethers": "^3.0.0", - "@nomicfoundation/hardhat-network-helpers": "^1.0.6", - "@nomicfoundation/hardhat-toolbox": "^5.0.0", - "@nomicfoundation/hardhat-verify": "^2.0.12", - "@openzeppelin/contracts": "^5.1.0", - "@openzeppelin/hardhat-upgrades": "^3.6.0", - "@trivago/prettier-plugin-sort-imports": "^4.0.0", - "@typechain/ethers-v6": "^0.5.1", - "@typechain/hardhat": "^9.1.0", - "@types/chai": "^4.3.4", - "@types/eslint__js": "^8.42.3", - "@types/fs-extra": "^9.0.13", - "@types/jest": "^29.5.14", - "@types/node": "^18.19.67", - "@typescript-eslint/eslint-plugin": "^8.0.1", - "@typescript-eslint/parser": "^8.0.1", - "chai": "^4.3.7", - "cross-env": "^7.0.3", - "dotenv": "^16.0.3", - "eslint": "^9.9.0", - "eslint-config-prettier": "^8.5.0", - "ethers": "^6.8.0", - "extra-bigint": "^1.1.18", - "fhevm": "^0.6.0", - "fhevm-core-contracts": "0.6.0-5", - "fhevmjs": "^0.6.0", - "fs-extra": "^10.1.0", - "globals": "^15.9.0", - "hardhat": "^2.22.8", - "hardhat-deploy": "^0.12.4", - "hardhat-gas-reporter": "^1.0.9", - "hardhat-ignore-warnings": "^0.2.11", - "hardhat-preprocessor": "^0.1.5", - "lodash": "^4.17.21", - "prettier": "^2.8.4", - "prettier-plugin-solidity": "^1.1.2", - "rimraf": "^4.1.2", - "sha3": "^2.1.4", - "solhint": "^3.4.0", - "solhint-plugin-prettier": "^0.0.5", - "solidity-coverage": "0.8.12", - "sqlite3": "^5.1.7", - "ts-generator": "^0.1.1", - "ts-jest": "^29.2.5", - "ts-node": "^10.9.1", - "typechain": "^8.2.0", - "typescript": "^5.5.4", - "typescript-eslint": "^8.0.1", - "web3-validator": "^2.0.6" - }, - "files": [ - "contracts" - ], - "keywords": [ - "blockchain", - "ethers", - "ethereum", - "hardhat", - "smart-contracts", - "solidity", - "template", - "typescript", - "typechain" - ], - "publishConfig": { - "access": "public" - }, - "scripts": { - "clean": "rimraf ./artifacts ./cache ./coverage ./types ./coverage.json && pnpm typechain", - "compile": "cross-env TS_NODE_TRANSPILE_ONLY=true hardhat compile", - "lint": "pnpm lint:sol && pnpm lint:ts && pnpm prettier:check", - "lint:sol": "solhint --max-warnings 25 \"contracts/**/*.sol\"", - "lint:ts": "eslint .", - "postinstall": "DOTENV_CONFIG_PATH=./.env.example pnpm typechain", - "prettier:check": "prettier --check \"**/*.{js,json,md,sol,ts,yml}\"", - "prettier:write": "prettier --write \"**/*.{js,json,md,sol,ts,yml}\"", - "typechain": "cross-env TS_NODE_TRANSPILE_ONLY=true hardhat typechain", - "test": "hardhat test --network hardhat", - "coverage": "hardhat coverage", - "deploy-sepolia": "hardhat deploy --network sepolia" - }, - "dependencies": { - "bigint-buffer": "^1.1.5", - "fhevm-contracts": "^0.2.0" - } -} diff --git a/contracts/pnpm-lock.yaml b/contracts/pnpm-lock.yaml deleted file mode 100644 index 11f2454..0000000 --- a/contracts/pnpm-lock.yaml +++ /dev/null @@ -1,8009 +0,0 @@ -lockfileVersion: '6.0' - -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - -dependencies: - bigint-buffer: - specifier: ^1.1.5 - version: 1.1.5 - fhevm-contracts: - specifier: ^0.2.0 - version: 0.2.0 - -devDependencies: - '@eslint/js': - specifier: ^9.9.0 - version: 9.16.0 - '@nomicfoundation/hardhat-chai-matchers': - specifier: ^2.0.0 - version: 2.0.8(@nomicfoundation/hardhat-ethers@3.0.8)(chai@4.5.0)(ethers@6.13.4)(hardhat@2.22.17) - '@nomicfoundation/hardhat-ethers': - specifier: ^3.0.0 - version: 3.0.8(ethers@6.13.4)(hardhat@2.22.17) - '@nomicfoundation/hardhat-network-helpers': - specifier: ^1.0.6 - version: 1.0.12(hardhat@2.22.17) - '@nomicfoundation/hardhat-toolbox': - specifier: ^5.0.0 - version: 5.0.0(@nomicfoundation/hardhat-chai-matchers@2.0.8)(@nomicfoundation/hardhat-ethers@3.0.8)(@nomicfoundation/hardhat-ignition-ethers@0.15.8)(@nomicfoundation/hardhat-network-helpers@1.0.12)(@nomicfoundation/hardhat-verify@2.0.12)(@typechain/ethers-v6@0.5.1)(@typechain/hardhat@9.1.0)(@types/chai@4.3.20)(@types/mocha@10.0.10)(@types/node@18.19.67)(chai@4.5.0)(ethers@6.13.4)(hardhat-gas-reporter@1.0.10)(hardhat@2.22.17)(solidity-coverage@0.8.12)(ts-node@10.9.2)(typechain@8.3.2)(typescript@5.7.2) - '@nomicfoundation/hardhat-verify': - specifier: ^2.0.12 - version: 2.0.12(hardhat@2.22.17) - '@openzeppelin/contracts': - specifier: ^5.1.0 - version: 5.1.0 - '@openzeppelin/hardhat-upgrades': - specifier: ^3.6.0 - version: 3.6.0(@nomicfoundation/hardhat-ethers@3.0.8)(@nomicfoundation/hardhat-verify@2.0.12)(ethers@6.13.4)(hardhat@2.22.17) - '@trivago/prettier-plugin-sort-imports': - specifier: ^4.0.0 - version: 4.3.0(prettier@2.8.8) - '@typechain/ethers-v6': - specifier: ^0.5.1 - version: 0.5.1(ethers@6.13.4)(typechain@8.3.2)(typescript@5.7.2) - '@typechain/hardhat': - specifier: ^9.1.0 - version: 9.1.0(@typechain/ethers-v6@0.5.1)(ethers@6.13.4)(hardhat@2.22.17)(typechain@8.3.2) - '@types/chai': - specifier: ^4.3.4 - version: 4.3.20 - '@types/eslint__js': - specifier: ^8.42.3 - version: 8.42.3 - '@types/fs-extra': - specifier: ^9.0.13 - version: 9.0.13 - '@types/jest': - specifier: ^29.5.14 - version: 29.5.14 - '@types/node': - specifier: ^18.19.67 - version: 18.19.67 - '@typescript-eslint/eslint-plugin': - specifier: ^8.0.1 - version: 8.17.0(@typescript-eslint/parser@8.17.0)(eslint@9.16.0)(typescript@5.7.2) - '@typescript-eslint/parser': - specifier: ^8.0.1 - version: 8.17.0(eslint@9.16.0)(typescript@5.7.2) - chai: - specifier: ^4.3.7 - version: 4.5.0 - cross-env: - specifier: ^7.0.3 - version: 7.0.3 - dotenv: - specifier: ^16.0.3 - version: 16.4.6 - eslint: - specifier: ^9.9.0 - version: 9.16.0 - eslint-config-prettier: - specifier: ^8.5.0 - version: 8.10.0(eslint@9.16.0) - ethers: - specifier: ^6.8.0 - version: 6.13.4 - extra-bigint: - specifier: ^1.1.18 - version: 1.2.0 - fhevm: - specifier: ^0.6.0 - version: 0.6.0 - fhevm-core-contracts: - specifier: 0.6.0-5 - version: 0.6.0-5 - fhevmjs: - specifier: ^0.6.0 - version: 0.6.0 - fs-extra: - specifier: ^10.1.0 - version: 10.1.0 - globals: - specifier: ^15.9.0 - version: 15.13.0 - hardhat: - specifier: ^2.22.8 - version: 2.22.17(ts-node@10.9.2)(typescript@5.7.2) - hardhat-deploy: - specifier: ^0.12.4 - version: 0.12.4 - hardhat-gas-reporter: - specifier: ^1.0.9 - version: 1.0.10(hardhat@2.22.17) - hardhat-ignore-warnings: - specifier: ^0.2.11 - version: 0.2.12 - hardhat-preprocessor: - specifier: ^0.1.5 - version: 0.1.5(hardhat@2.22.17) - lodash: - specifier: ^4.17.21 - version: 4.17.21 - prettier: - specifier: ^2.8.4 - version: 2.8.8 - prettier-plugin-solidity: - specifier: ^1.1.2 - version: 1.4.1(prettier@2.8.8) - rimraf: - specifier: ^4.1.2 - version: 4.4.1 - sha3: - specifier: ^2.1.4 - version: 2.1.4 - solhint: - specifier: ^3.4.0 - version: 3.6.2(typescript@5.7.2) - solhint-plugin-prettier: - specifier: ^0.0.5 - version: 0.0.5(prettier-plugin-solidity@1.4.1)(prettier@2.8.8) - solidity-coverage: - specifier: 0.8.12 - version: 0.8.12(hardhat@2.22.17) - sqlite3: - specifier: ^5.1.7 - version: 5.1.7 - ts-generator: - specifier: ^0.1.1 - version: 0.1.1 - ts-jest: - specifier: ^29.2.5 - version: 29.2.5(@babel/core@7.26.0)(jest@29.7.0)(typescript@5.7.2) - ts-node: - specifier: ^10.9.1 - version: 10.9.2(@types/node@18.19.67)(typescript@5.7.2) - typechain: - specifier: ^8.2.0 - version: 8.3.2(typescript@5.7.2) - typescript: - specifier: ^5.5.4 - version: 5.7.2 - typescript-eslint: - specifier: ^8.0.1 - version: 8.17.0(eslint@9.16.0)(typescript@5.7.2) - web3-validator: - specifier: ^2.0.6 - version: 2.0.6 - -packages: - - /@adraffy/ens-normalize@1.10.1: - resolution: {integrity: sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==} - dev: true - - /@ampproject/remapping@2.3.0: - resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - dev: true - - /@aws-crypto/sha256-js@1.2.2: - resolution: {integrity: sha512-Nr1QJIbW/afYYGzYvrF70LtaHrIRtd4TNAglX8BvlfxJLZ45SAmueIKYl5tWoNBPzp65ymXGFK0Bb1vZUpuc9g==} - dependencies: - '@aws-crypto/util': 1.2.2 - '@aws-sdk/types': 3.696.0 - tslib: 1.14.1 - dev: true - - /@aws-crypto/util@1.2.2: - resolution: {integrity: sha512-H8PjG5WJ4wz0UXAFXeJjWCW1vkvIJ3qUUD+rGRwJ2/hj+xT58Qle2MTql/2MGzkU+1JLAFuR6aJpLAjHwhmwwg==} - dependencies: - '@aws-sdk/types': 3.696.0 - '@aws-sdk/util-utf8-browser': 3.259.0 - tslib: 1.14.1 - dev: true - - /@aws-sdk/types@3.696.0: - resolution: {integrity: sha512-9rTvUJIAj5d3//U5FDPWGJ1nFJLuWb30vugGOrWk7aNZ6y9tuA3PI7Cc9dP8WEXKVyK1vuuk8rSFP2iqXnlgrw==} - engines: {node: '>=16.0.0'} - dependencies: - '@smithy/types': 3.7.1 - tslib: 2.8.1 - dev: true - - /@aws-sdk/util-utf8-browser@3.259.0: - resolution: {integrity: sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==} - dependencies: - tslib: 2.8.1 - dev: true - - /@babel/code-frame@7.26.2: - resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-validator-identifier': 7.25.9 - js-tokens: 4.0.0 - picocolors: 1.1.1 - dev: true - - /@babel/compat-data@7.26.3: - resolution: {integrity: sha512-nHIxvKPniQXpmQLb0vhY3VaFb3S0YrTAwpOWJZh1wn3oJPjJk9Asva204PsBdmAE8vpzfHudT8DB0scYvy9q0g==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/core@7.26.0: - resolution: {integrity: sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==} - engines: {node: '>=6.9.0'} - dependencies: - '@ampproject/remapping': 2.3.0 - '@babel/code-frame': 7.26.2 - '@babel/generator': 7.26.3 - '@babel/helper-compilation-targets': 7.25.9 - '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.0) - '@babel/helpers': 7.26.0 - '@babel/parser': 7.26.3 - '@babel/template': 7.25.9 - '@babel/traverse': 7.26.3 - '@babel/types': 7.26.3 - convert-source-map: 2.0.0 - debug: 4.3.7(supports-color@8.1.1) - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/generator@7.17.7: - resolution: {integrity: sha512-oLcVCTeIFadUoArDTwpluncplrYBmTCCZZgXCbgNGvOBBiSDDK3eWO4b/+eOTli5tKv1lg+a5/NAXg+nTcei1w==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.17.0 - jsesc: 2.5.2 - source-map: 0.5.7 - dev: true - - /@babel/generator@7.26.2: - resolution: {integrity: sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/parser': 7.26.2 - '@babel/types': 7.26.0 - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - jsesc: 3.0.2 - dev: true - - /@babel/generator@7.26.3: - resolution: {integrity: sha512-6FF/urZvD0sTeO7k6/B15pMLC4CHUv1426lzr3N01aHJTl046uCAh9LXW/fzeXXjPNCJ6iABW5XaWOsIZB93aQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/parser': 7.26.3 - '@babel/types': 7.26.3 - '@jridgewell/gen-mapping': 0.3.5 - '@jridgewell/trace-mapping': 0.3.25 - jsesc: 3.0.2 - dev: true - - /@babel/helper-compilation-targets@7.25.9: - resolution: {integrity: sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/compat-data': 7.26.3 - '@babel/helper-validator-option': 7.25.9 - browserslist: 4.24.2 - lru-cache: 5.1.1 - semver: 6.3.1 - dev: true - - /@babel/helper-environment-visitor@7.24.7: - resolution: {integrity: sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.26.0 - dev: true - - /@babel/helper-function-name@7.24.7: - resolution: {integrity: sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.25.9 - '@babel/types': 7.26.0 - dev: true - - /@babel/helper-hoist-variables@7.24.7: - resolution: {integrity: sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.26.0 - dev: true - - /@babel/helper-module-imports@7.25.9: - resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/traverse': 7.26.3 - '@babel/types': 7.26.3 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helper-module-transforms@7.26.0(@babel/core@7.26.0): - resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-module-imports': 7.25.9 - '@babel/helper-validator-identifier': 7.25.9 - '@babel/traverse': 7.26.3 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/helper-plugin-utils@7.25.9: - resolution: {integrity: sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-split-export-declaration@7.24.7: - resolution: {integrity: sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.26.0 - dev: true - - /@babel/helper-string-parser@7.25.9: - resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-validator-identifier@7.25.9: - resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helper-validator-option@7.25.9: - resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} - engines: {node: '>=6.9.0'} - dev: true - - /@babel/helpers@7.26.0: - resolution: {integrity: sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.25.9 - '@babel/types': 7.26.3 - dev: true - - /@babel/parser@7.26.2: - resolution: {integrity: sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==} - engines: {node: '>=6.0.0'} - hasBin: true - dependencies: - '@babel/types': 7.26.0 - dev: true - - /@babel/parser@7.26.3: - resolution: {integrity: sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==} - engines: {node: '>=6.0.0'} - hasBin: true - dependencies: - '@babel/types': 7.26.3 - dev: true - - /@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.26.0): - resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - dev: true - - /@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.26.0): - resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - dev: true - - /@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.26.0): - resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - dev: true - - /@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.26.0): - resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - dev: true - - /@babel/plugin-syntax-import-attributes@7.26.0(@babel/core@7.26.0): - resolution: {integrity: sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - dev: true - - /@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.26.0): - resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - dev: true - - /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.26.0): - resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - dev: true - - /@babel/plugin-syntax-jsx@7.25.9(@babel/core@7.26.0): - resolution: {integrity: sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - dev: true - - /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.26.0): - resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - dev: true - - /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.26.0): - resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - dev: true - - /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.26.0): - resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - dev: true - - /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.26.0): - resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - dev: true - - /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.26.0): - resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - dev: true - - /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.26.0): - resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - dev: true - - /@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.26.0): - resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - dev: true - - /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.26.0): - resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - dev: true - - /@babel/plugin-syntax-typescript@7.25.9(@babel/core@7.26.0): - resolution: {integrity: sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.26.0 - '@babel/helper-plugin-utils': 7.25.9 - dev: true - - /@babel/template@7.25.9: - resolution: {integrity: sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.26.2 - '@babel/parser': 7.26.2 - '@babel/types': 7.26.0 - dev: true - - /@babel/traverse@7.23.2: - resolution: {integrity: sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.26.2 - '@babel/generator': 7.26.2 - '@babel/helper-environment-visitor': 7.24.7 - '@babel/helper-function-name': 7.24.7 - '@babel/helper-hoist-variables': 7.24.7 - '@babel/helper-split-export-declaration': 7.24.7 - '@babel/parser': 7.26.2 - '@babel/types': 7.26.0 - debug: 4.3.7(supports-color@8.1.1) - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/traverse@7.26.3: - resolution: {integrity: sha512-yTmc8J+Sj8yLzwr4PD5Xb/WF3bOYu2C2OoSZPzbuqRm4n98XirsbzaX+GloeO376UnSYIYJ4NCanwV5/ugZkwA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.26.2 - '@babel/generator': 7.26.3 - '@babel/parser': 7.26.3 - '@babel/template': 7.25.9 - '@babel/types': 7.26.3 - debug: 4.3.7(supports-color@8.1.1) - globals: 11.12.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@babel/types@7.17.0: - resolution: {integrity: sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-validator-identifier': 7.25.9 - to-fast-properties: 2.0.0 - dev: true - - /@babel/types@7.26.0: - resolution: {integrity: sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-string-parser': 7.25.9 - '@babel/helper-validator-identifier': 7.25.9 - dev: true - - /@babel/types@7.26.3: - resolution: {integrity: sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-string-parser': 7.25.9 - '@babel/helper-validator-identifier': 7.25.9 - dev: true - - /@bcoe/v8-coverage@0.2.3: - resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} - dev: true - - /@bytecodealliance/preview2-shim@0.17.0: - resolution: {integrity: sha512-JorcEwe4ud0x5BS/Ar2aQWOQoFzjq/7jcnxYXCvSMh0oRm0dQXzOA+hqLDBnOMks1LLBA7dmiLLsEBl09Yd6iQ==} - dev: true - - /@cspotcode/source-map-support@0.8.1: - resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} - engines: {node: '>=12'} - dependencies: - '@jridgewell/trace-mapping': 0.3.9 - dev: true - - /@eslint-community/eslint-utils@4.4.1(eslint@9.16.0): - resolution: {integrity: sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - dependencies: - eslint: 9.16.0 - eslint-visitor-keys: 3.4.3 - dev: true - - /@eslint-community/regexpp@4.12.1: - resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - dev: true - - /@eslint/config-array@0.19.0: - resolution: {integrity: sha512-zdHg2FPIFNKPdcHWtiNT+jEFCHYVplAXRDlQDyqy0zGx/q2parwh7brGJSiTxRk/TSMkbM//zt/f5CHgyTyaSQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - dependencies: - '@eslint/object-schema': 2.1.4 - debug: 4.3.7(supports-color@8.1.1) - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@eslint/core@0.9.0: - resolution: {integrity: sha512-7ATR9F0e4W85D/0w7cU0SNj7qkAexMG+bAHEZOjo9akvGuhHE2m7umzWzfnpa0XAg5Kxc1BWmtPMV67jJ+9VUg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - dev: true - - /@eslint/eslintrc@3.2.0: - resolution: {integrity: sha512-grOjVNN8P3hjJn/eIETF1wwd12DdnwFDoyceUJLYYdkpbwq3nLi+4fqrTAONx7XDALqlL220wC/RHSC/QTI/0w==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - dependencies: - ajv: 6.12.6 - debug: 4.3.7(supports-color@8.1.1) - espree: 10.3.0 - globals: 14.0.0 - ignore: 5.3.2 - import-fresh: 3.3.0 - js-yaml: 4.1.0 - minimatch: 3.1.2 - strip-json-comments: 3.1.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@eslint/js@9.16.0: - resolution: {integrity: sha512-tw2HxzQkrbeuvyj1tG2Yqq+0H9wGoI2IMk4EOsQeX+vmd75FtJAzf+gTA69WF+baUKRYQ3x2kbLE08js5OsTVg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - dev: true - - /@eslint/object-schema@2.1.4: - resolution: {integrity: sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - dev: true - - /@eslint/plugin-kit@0.2.3: - resolution: {integrity: sha512-2b/g5hRmpbb1o4GnTZax9N9m0FXzz9OV42ZzI4rDDMDuHUqigAiQCEWChBWCY4ztAGVRjoWT19v0yMmc5/L5kA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - dependencies: - levn: 0.4.1 - dev: true - - /@ethereumjs/rlp@4.0.1: - resolution: {integrity: sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw==} - engines: {node: '>=14'} - hasBin: true - dev: true - - /@ethereumjs/util@8.1.0: - resolution: {integrity: sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA==} - engines: {node: '>=14'} - dependencies: - '@ethereumjs/rlp': 4.0.1 - ethereum-cryptography: 2.2.1 - micro-ftch: 0.3.1 - dev: true - - /@ethersproject/abi@5.7.0: - resolution: {integrity: sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA==} - dependencies: - '@ethersproject/address': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/constants': 5.7.0 - '@ethersproject/hash': 5.7.0 - '@ethersproject/keccak256': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/strings': 5.7.0 - dev: true - - /@ethersproject/abstract-provider@5.7.0: - resolution: {integrity: sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==} - dependencies: - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/networks': 5.7.1 - '@ethersproject/properties': 5.7.0 - '@ethersproject/transactions': 5.7.0 - '@ethersproject/web': 5.7.1 - dev: true - - /@ethersproject/abstract-signer@5.7.0: - resolution: {integrity: sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ==} - dependencies: - '@ethersproject/abstract-provider': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 - dev: true - - /@ethersproject/address@5.6.1: - resolution: {integrity: sha512-uOgF0kS5MJv9ZvCz7x6T2EXJSzotiybApn4XlOgoTX0xdtyVIJ7pF+6cGPxiEq/dpBiTfMiw7Yc81JcwhSYA0Q==} - dependencies: - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/keccak256': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/rlp': 5.7.0 - dev: true - - /@ethersproject/address@5.7.0: - resolution: {integrity: sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==} - dependencies: - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/keccak256': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/rlp': 5.7.0 - dev: true - - /@ethersproject/base64@5.7.0: - resolution: {integrity: sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==} - dependencies: - '@ethersproject/bytes': 5.7.0 - dev: true - - /@ethersproject/basex@5.7.0: - resolution: {integrity: sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw==} - dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/properties': 5.7.0 - dev: true - - /@ethersproject/bignumber@5.7.0: - resolution: {integrity: sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==} - dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 - bn.js: 5.2.1 - dev: true - - /@ethersproject/bytes@5.7.0: - resolution: {integrity: sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==} - dependencies: - '@ethersproject/logger': 5.7.0 - dev: true - - /@ethersproject/constants@5.7.0: - resolution: {integrity: sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==} - dependencies: - '@ethersproject/bignumber': 5.7.0 - dev: true - - /@ethersproject/contracts@5.7.0: - resolution: {integrity: sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg==} - dependencies: - '@ethersproject/abi': 5.7.0 - '@ethersproject/abstract-provider': 5.7.0 - '@ethersproject/abstract-signer': 5.7.0 - '@ethersproject/address': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/constants': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/transactions': 5.7.0 - dev: true - - /@ethersproject/hash@5.7.0: - resolution: {integrity: sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==} - dependencies: - '@ethersproject/abstract-signer': 5.7.0 - '@ethersproject/address': 5.7.0 - '@ethersproject/base64': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/keccak256': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/strings': 5.7.0 - dev: true - - /@ethersproject/hdnode@5.7.0: - resolution: {integrity: sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg==} - dependencies: - '@ethersproject/abstract-signer': 5.7.0 - '@ethersproject/basex': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/pbkdf2': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/sha2': 5.7.0 - '@ethersproject/signing-key': 5.7.0 - '@ethersproject/strings': 5.7.0 - '@ethersproject/transactions': 5.7.0 - '@ethersproject/wordlists': 5.7.0 - dev: true - - /@ethersproject/json-wallets@5.7.0: - resolution: {integrity: sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g==} - dependencies: - '@ethersproject/abstract-signer': 5.7.0 - '@ethersproject/address': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/hdnode': 5.7.0 - '@ethersproject/keccak256': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/pbkdf2': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/random': 5.7.0 - '@ethersproject/strings': 5.7.0 - '@ethersproject/transactions': 5.7.0 - aes-js: 3.0.0 - scrypt-js: 3.0.1 - dev: true - - /@ethersproject/keccak256@5.7.0: - resolution: {integrity: sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==} - dependencies: - '@ethersproject/bytes': 5.7.0 - js-sha3: 0.8.0 - dev: true - - /@ethersproject/logger@5.7.0: - resolution: {integrity: sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==} - dev: true - - /@ethersproject/networks@5.7.1: - resolution: {integrity: sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==} - dependencies: - '@ethersproject/logger': 5.7.0 - dev: true - - /@ethersproject/pbkdf2@5.7.0: - resolution: {integrity: sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw==} - dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/sha2': 5.7.0 - dev: true - - /@ethersproject/properties@5.7.0: - resolution: {integrity: sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==} - dependencies: - '@ethersproject/logger': 5.7.0 - dev: true - - /@ethersproject/providers@5.7.2: - resolution: {integrity: sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg==} - dependencies: - '@ethersproject/abstract-provider': 5.7.0 - '@ethersproject/abstract-signer': 5.7.0 - '@ethersproject/address': 5.7.0 - '@ethersproject/base64': 5.7.0 - '@ethersproject/basex': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/constants': 5.7.0 - '@ethersproject/hash': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/networks': 5.7.1 - '@ethersproject/properties': 5.7.0 - '@ethersproject/random': 5.7.0 - '@ethersproject/rlp': 5.7.0 - '@ethersproject/sha2': 5.7.0 - '@ethersproject/strings': 5.7.0 - '@ethersproject/transactions': 5.7.0 - '@ethersproject/web': 5.7.1 - bech32: 1.1.4 - ws: 7.4.6 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - dev: true - - /@ethersproject/random@5.7.0: - resolution: {integrity: sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ==} - dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 - dev: true - - /@ethersproject/rlp@5.7.0: - resolution: {integrity: sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==} - dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 - dev: true - - /@ethersproject/sha2@5.7.0: - resolution: {integrity: sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw==} - dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 - hash.js: 1.1.7 - dev: true - - /@ethersproject/signing-key@5.7.0: - resolution: {integrity: sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==} - dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 - bn.js: 5.2.1 - elliptic: 6.5.4 - hash.js: 1.1.7 - dev: true - - /@ethersproject/solidity@5.7.0: - resolution: {integrity: sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA==} - dependencies: - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/keccak256': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/sha2': 5.7.0 - '@ethersproject/strings': 5.7.0 - dev: true - - /@ethersproject/strings@5.7.0: - resolution: {integrity: sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==} - dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/constants': 5.7.0 - '@ethersproject/logger': 5.7.0 - dev: true - - /@ethersproject/transactions@5.7.0: - resolution: {integrity: sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==} - dependencies: - '@ethersproject/address': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/constants': 5.7.0 - '@ethersproject/keccak256': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/rlp': 5.7.0 - '@ethersproject/signing-key': 5.7.0 - dev: true - - /@ethersproject/units@5.7.0: - resolution: {integrity: sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg==} - dependencies: - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/constants': 5.7.0 - '@ethersproject/logger': 5.7.0 - dev: true - - /@ethersproject/wallet@5.7.0: - resolution: {integrity: sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA==} - dependencies: - '@ethersproject/abstract-provider': 5.7.0 - '@ethersproject/abstract-signer': 5.7.0 - '@ethersproject/address': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/hash': 5.7.0 - '@ethersproject/hdnode': 5.7.0 - '@ethersproject/json-wallets': 5.7.0 - '@ethersproject/keccak256': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/random': 5.7.0 - '@ethersproject/signing-key': 5.7.0 - '@ethersproject/transactions': 5.7.0 - '@ethersproject/wordlists': 5.7.0 - dev: true - - /@ethersproject/web@5.7.1: - resolution: {integrity: sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==} - dependencies: - '@ethersproject/base64': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/strings': 5.7.0 - dev: true - - /@ethersproject/wordlists@5.7.0: - resolution: {integrity: sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA==} - dependencies: - '@ethersproject/bytes': 5.7.0 - '@ethersproject/hash': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/strings': 5.7.0 - dev: true - - /@fastify/busboy@2.1.1: - resolution: {integrity: sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==} - engines: {node: '>=14'} - dev: true - - /@gar/promisify@1.1.3: - resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==} - requiresBuild: true - optional: true - - /@humanfs/core@0.19.1: - resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} - engines: {node: '>=18.18.0'} - dev: true - - /@humanfs/node@0.16.6: - resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==} - engines: {node: '>=18.18.0'} - dependencies: - '@humanfs/core': 0.19.1 - '@humanwhocodes/retry': 0.3.1 - dev: true - - /@humanwhocodes/module-importer@1.0.1: - resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} - engines: {node: '>=12.22'} - dev: true - - /@humanwhocodes/retry@0.3.1: - resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} - engines: {node: '>=18.18'} - dev: true - - /@humanwhocodes/retry@0.4.1: - resolution: {integrity: sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==} - engines: {node: '>=18.18'} - dev: true - - /@istanbuljs/load-nyc-config@1.1.0: - resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} - engines: {node: '>=8'} - dependencies: - camelcase: 5.3.1 - find-up: 4.1.0 - get-package-type: 0.1.0 - js-yaml: 3.14.1 - resolve-from: 5.0.0 - dev: true - - /@istanbuljs/schema@0.1.3: - resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} - engines: {node: '>=8'} - dev: true - - /@jest/console@29.7.0: - resolution: {integrity: sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.6.3 - '@types/node': 18.19.67 - chalk: 4.1.2 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - slash: 3.0.0 - dev: true - - /@jest/core@29.7.0(ts-node@10.9.2): - resolution: {integrity: sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - dependencies: - '@jest/console': 29.7.0 - '@jest/reporters': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 18.19.67 - ansi-escapes: 4.3.2 - chalk: 4.1.2 - ci-info: 3.9.0 - exit: 0.1.2 - graceful-fs: 4.2.11 - jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@18.19.67)(ts-node@10.9.2) - jest-haste-map: 29.7.0 - jest-message-util: 29.7.0 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-resolve-dependencies: 29.7.0 - jest-runner: 29.7.0 - jest-runtime: 29.7.0 - jest-snapshot: 29.7.0 - jest-util: 29.7.0 - jest-validate: 29.7.0 - jest-watcher: 29.7.0 - micromatch: 4.0.8 - pretty-format: 29.7.0 - slash: 3.0.0 - strip-ansi: 6.0.1 - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - - ts-node - dev: true - - /@jest/environment@29.7.0: - resolution: {integrity: sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/fake-timers': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 18.19.67 - jest-mock: 29.7.0 - dev: true - - /@jest/expect-utils@29.7.0: - resolution: {integrity: sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - jest-get-type: 29.6.3 - dev: true - - /@jest/expect@29.7.0: - resolution: {integrity: sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - expect: 29.7.0 - jest-snapshot: 29.7.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@jest/fake-timers@29.7.0: - resolution: {integrity: sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.6.3 - '@sinonjs/fake-timers': 10.3.0 - '@types/node': 18.19.67 - jest-message-util: 29.7.0 - jest-mock: 29.7.0 - jest-util: 29.7.0 - dev: true - - /@jest/globals@29.7.0: - resolution: {integrity: sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/environment': 29.7.0 - '@jest/expect': 29.7.0 - '@jest/types': 29.6.3 - jest-mock: 29.7.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@jest/reporters@29.7.0: - resolution: {integrity: sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - dependencies: - '@bcoe/v8-coverage': 0.2.3 - '@jest/console': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@jridgewell/trace-mapping': 0.3.25 - '@types/node': 18.19.67 - chalk: 4.1.2 - collect-v8-coverage: 1.0.2 - exit: 0.1.2 - glob: 7.2.3 - graceful-fs: 4.2.11 - istanbul-lib-coverage: 3.2.2 - istanbul-lib-instrument: 6.0.3 - istanbul-lib-report: 3.0.1 - istanbul-lib-source-maps: 4.0.1 - istanbul-reports: 3.1.7 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - jest-worker: 29.7.0 - slash: 3.0.0 - string-length: 4.0.2 - strip-ansi: 6.0.1 - v8-to-istanbul: 9.3.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@jest/schemas@29.6.3: - resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@sinclair/typebox': 0.27.8 - dev: true - - /@jest/source-map@29.6.3: - resolution: {integrity: sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jridgewell/trace-mapping': 0.3.25 - callsites: 3.1.0 - graceful-fs: 4.2.11 - dev: true - - /@jest/test-result@29.7.0: - resolution: {integrity: sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/console': 29.7.0 - '@jest/types': 29.6.3 - '@types/istanbul-lib-coverage': 2.0.6 - collect-v8-coverage: 1.0.2 - dev: true - - /@jest/test-sequencer@29.7.0: - resolution: {integrity: sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/test-result': 29.7.0 - graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - slash: 3.0.0 - dev: true - - /@jest/transform@29.7.0: - resolution: {integrity: sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@babel/core': 7.26.0 - '@jest/types': 29.6.3 - '@jridgewell/trace-mapping': 0.3.25 - babel-plugin-istanbul: 6.1.1 - chalk: 4.1.2 - convert-source-map: 2.0.0 - fast-json-stable-stringify: 2.1.0 - graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - jest-regex-util: 29.6.3 - jest-util: 29.7.0 - micromatch: 4.0.8 - pirates: 4.0.6 - slash: 3.0.0 - write-file-atomic: 4.0.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@jest/types@29.6.3: - resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/schemas': 29.6.3 - '@types/istanbul-lib-coverage': 2.0.6 - '@types/istanbul-reports': 3.0.4 - '@types/node': 18.19.67 - '@types/yargs': 17.0.33 - chalk: 4.1.2 - dev: true - - /@jridgewell/gen-mapping@0.3.5: - resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} - engines: {node: '>=6.0.0'} - dependencies: - '@jridgewell/set-array': 1.2.1 - '@jridgewell/sourcemap-codec': 1.5.0 - '@jridgewell/trace-mapping': 0.3.25 - dev: true - - /@jridgewell/resolve-uri@3.1.2: - resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} - engines: {node: '>=6.0.0'} - dev: true - - /@jridgewell/set-array@1.2.1: - resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} - engines: {node: '>=6.0.0'} - dev: true - - /@jridgewell/sourcemap-codec@1.5.0: - resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} - dev: true - - /@jridgewell/trace-mapping@0.3.25: - resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.0 - dev: true - - /@jridgewell/trace-mapping@0.3.9: - resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.0 - dev: true - - /@metamask/eth-sig-util@4.0.1: - resolution: {integrity: sha512-tghyZKLHZjcdlDqCA3gNZmLeR0XvOE9U1qoQO9ohyAZT6Pya+H9vkBPcsyXytmYLNgVoin7CKCmweo/R43V+tQ==} - engines: {node: '>=12.0.0'} - dependencies: - ethereumjs-abi: 0.6.8 - ethereumjs-util: 6.2.1 - ethjs-util: 0.1.6 - tweetnacl: 1.0.3 - tweetnacl-util: 0.15.1 - dev: true - - /@noble/curves@1.2.0: - resolution: {integrity: sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==} - dependencies: - '@noble/hashes': 1.3.2 - dev: true - - /@noble/curves@1.4.2: - resolution: {integrity: sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==} - dependencies: - '@noble/hashes': 1.4.0 - dev: true - - /@noble/hashes@1.2.0: - resolution: {integrity: sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==} - dev: true - - /@noble/hashes@1.3.2: - resolution: {integrity: sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==} - engines: {node: '>= 16'} - dev: true - - /@noble/hashes@1.4.0: - resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==} - engines: {node: '>= 16'} - dev: true - - /@noble/hashes@1.6.1: - resolution: {integrity: sha512-pq5D8h10hHBjyqX+cfBm0i8JUXJ0UhczFc4r74zbuT9XgewFo2E3J1cOaGtdZynILNmQ685YWGzGE1Zv6io50w==} - engines: {node: ^14.21.3 || >=16} - dev: true - - /@noble/secp256k1@1.7.1: - resolution: {integrity: sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==} - dev: true - - /@nodelib/fs.scandir@2.1.5: - resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} - engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 - dev: true - - /@nodelib/fs.stat@2.0.5: - resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} - engines: {node: '>= 8'} - dev: true - - /@nodelib/fs.walk@1.2.8: - resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} - engines: {node: '>= 8'} - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.17.1 - dev: true - - /@nomicfoundation/edr-darwin-arm64@0.6.5: - resolution: {integrity: sha512-A9zCCbbNxBpLgjS1kEJSpqxIvGGAX4cYbpDYCU2f3jVqOwaZ/NU761y1SvuCRVpOwhoCXqByN9b7HPpHi0L4hw==} - engines: {node: '>= 18'} - dev: true - - /@nomicfoundation/edr-darwin-x64@0.6.5: - resolution: {integrity: sha512-x3zBY/v3R0modR5CzlL6qMfFMdgwd6oHrWpTkuuXnPFOX8SU31qq87/230f4szM+ukGK8Hi+mNq7Ro2VF4Fj+w==} - engines: {node: '>= 18'} - dev: true - - /@nomicfoundation/edr-linux-arm64-gnu@0.6.5: - resolution: {integrity: sha512-HGpB8f1h8ogqPHTyUpyPRKZxUk2lu061g97dOQ/W4CxevI0s/qiw5DB3U3smLvSnBHKOzYS1jkxlMeGN01ky7A==} - engines: {node: '>= 18'} - dev: true - - /@nomicfoundation/edr-linux-arm64-musl@0.6.5: - resolution: {integrity: sha512-ESvJM5Y9XC03fZg9KaQg3Hl+mbx7dsSkTIAndoJS7X2SyakpL9KZpOSYrDk135o8s9P9lYJdPOyiq+Sh+XoCbQ==} - engines: {node: '>= 18'} - dev: true - - /@nomicfoundation/edr-linux-x64-gnu@0.6.5: - resolution: {integrity: sha512-HCM1usyAR1Ew6RYf5AkMYGvHBy64cPA5NMbaeY72r0mpKaH3txiMyydcHibByOGdQ8iFLWpyUdpl1egotw+Tgg==} - engines: {node: '>= 18'} - dev: true - - /@nomicfoundation/edr-linux-x64-musl@0.6.5: - resolution: {integrity: sha512-nB2uFRyczhAvWUH7NjCsIO6rHnQrof3xcCe6Mpmnzfl2PYcGyxN7iO4ZMmRcQS7R1Y670VH6+8ZBiRn8k43m7A==} - engines: {node: '>= 18'} - dev: true - - /@nomicfoundation/edr-win32-x64-msvc@0.6.5: - resolution: {integrity: sha512-B9QD/4DSSCFtWicO8A3BrsnitO1FPv7axB62wq5Q+qeJ50yJlTmyeGY3cw62gWItdvy2mh3fRM6L1LpnHiB77A==} - engines: {node: '>= 18'} - dev: true - - /@nomicfoundation/edr@0.6.5: - resolution: {integrity: sha512-tAqMslLP+/2b2sZP4qe9AuGxG3OkQ5gGgHE4isUuq6dUVjwCRPFhAOhpdFl+OjY5P3yEv3hmq9HjUGRa2VNjng==} - engines: {node: '>= 18'} - dependencies: - '@nomicfoundation/edr-darwin-arm64': 0.6.5 - '@nomicfoundation/edr-darwin-x64': 0.6.5 - '@nomicfoundation/edr-linux-arm64-gnu': 0.6.5 - '@nomicfoundation/edr-linux-arm64-musl': 0.6.5 - '@nomicfoundation/edr-linux-x64-gnu': 0.6.5 - '@nomicfoundation/edr-linux-x64-musl': 0.6.5 - '@nomicfoundation/edr-win32-x64-msvc': 0.6.5 - dev: true - - /@nomicfoundation/ethereumjs-common@4.0.4: - resolution: {integrity: sha512-9Rgb658lcWsjiicr5GzNCjI1llow/7r0k50dLL95OJ+6iZJcVbi15r3Y0xh2cIO+zgX0WIHcbzIu6FeQf9KPrg==} - dependencies: - '@nomicfoundation/ethereumjs-util': 9.0.4 - transitivePeerDependencies: - - c-kzg - dev: true - - /@nomicfoundation/ethereumjs-rlp@5.0.4: - resolution: {integrity: sha512-8H1S3s8F6QueOc/X92SdrA4RDenpiAEqMg5vJH99kcQaCy/a3Q6fgseo75mgWlbanGJXSlAPtnCeG9jvfTYXlw==} - engines: {node: '>=18'} - hasBin: true - dev: true - - /@nomicfoundation/ethereumjs-tx@5.0.4: - resolution: {integrity: sha512-Xjv8wAKJGMrP1f0n2PeyfFCCojHd7iS3s/Ab7qzF1S64kxZ8Z22LCMynArYsVqiFx6rzYy548HNVEyI+AYN/kw==} - engines: {node: '>=18'} - peerDependencies: - c-kzg: ^2.1.2 - peerDependenciesMeta: - c-kzg: - optional: true - dependencies: - '@nomicfoundation/ethereumjs-common': 4.0.4 - '@nomicfoundation/ethereumjs-rlp': 5.0.4 - '@nomicfoundation/ethereumjs-util': 9.0.4 - ethereum-cryptography: 0.1.3 - dev: true - - /@nomicfoundation/ethereumjs-util@9.0.4: - resolution: {integrity: sha512-sLOzjnSrlx9Bb9EFNtHzK/FJFsfg2re6bsGqinFinH1gCqVfz9YYlXiMWwDM4C/L4ywuHFCYwfKTVr/QHQcU0Q==} - engines: {node: '>=18'} - peerDependencies: - c-kzg: ^2.1.2 - peerDependenciesMeta: - c-kzg: - optional: true - dependencies: - '@nomicfoundation/ethereumjs-rlp': 5.0.4 - ethereum-cryptography: 0.1.3 - dev: true - - /@nomicfoundation/hardhat-chai-matchers@2.0.8(@nomicfoundation/hardhat-ethers@3.0.8)(chai@4.5.0)(ethers@6.13.4)(hardhat@2.22.17): - resolution: {integrity: sha512-Z5PiCXH4xhNLASROlSUOADfhfpfhYO6D7Hn9xp8PddmHey0jq704cr6kfU8TRrQ4PUZbpfsZadPj+pCfZdjPIg==} - peerDependencies: - '@nomicfoundation/hardhat-ethers': ^3.0.0 - chai: ^4.2.0 - ethers: ^6.1.0 - hardhat: ^2.9.4 - dependencies: - '@nomicfoundation/hardhat-ethers': 3.0.8(ethers@6.13.4)(hardhat@2.22.17) - '@types/chai-as-promised': 7.1.8 - chai: 4.5.0 - chai-as-promised: 7.1.2(chai@4.5.0) - deep-eql: 4.1.4 - ethers: 6.13.4 - hardhat: 2.22.17(ts-node@10.9.2)(typescript@5.7.2) - ordinal: 1.0.3 - dev: true - - /@nomicfoundation/hardhat-ethers@3.0.8(ethers@6.13.4)(hardhat@2.22.17): - resolution: {integrity: sha512-zhOZ4hdRORls31DTOqg+GmEZM0ujly8GGIuRY7t7szEk2zW/arY1qDug/py8AEktT00v5K+b6RvbVog+va51IA==} - peerDependencies: - ethers: ^6.1.0 - hardhat: ^2.0.0 - dependencies: - debug: 4.3.7(supports-color@8.1.1) - ethers: 6.13.4 - hardhat: 2.22.17(ts-node@10.9.2)(typescript@5.7.2) - lodash.isequal: 4.5.0 - transitivePeerDependencies: - - supports-color - dev: true - - /@nomicfoundation/hardhat-ignition-ethers@0.15.8(@nomicfoundation/hardhat-ethers@3.0.8)(@nomicfoundation/hardhat-ignition@0.15.8)(@nomicfoundation/ignition-core@0.15.8)(ethers@6.13.4)(hardhat@2.22.17): - resolution: {integrity: sha512-5Ev8cXBKgqqOsFXxWe8iijsRabWGd/Vclx3SC903KeKVePdssVsZcYTtRNRcIwRcPJ0RIKJPIZz7MNDo64l3+w==} - peerDependencies: - '@nomicfoundation/hardhat-ethers': ^3.0.4 - '@nomicfoundation/hardhat-ignition': ^0.15.8 - '@nomicfoundation/ignition-core': ^0.15.8 - ethers: ^6.7.0 - hardhat: ^2.18.0 - dependencies: - '@nomicfoundation/hardhat-ethers': 3.0.8(ethers@6.13.4)(hardhat@2.22.17) - '@nomicfoundation/hardhat-ignition': 0.15.8(@nomicfoundation/hardhat-verify@2.0.12)(hardhat@2.22.17) - '@nomicfoundation/ignition-core': 0.15.8 - ethers: 6.13.4 - hardhat: 2.22.17(ts-node@10.9.2)(typescript@5.7.2) - dev: true - - /@nomicfoundation/hardhat-ignition@0.15.8(@nomicfoundation/hardhat-verify@2.0.12)(hardhat@2.22.17): - resolution: {integrity: sha512-TN8TFQokcd7VyqGfbXO+KS8Q4K/gmsOFlv8dPnt/N596AncgV2Igxh5C3O+KVez11PDHNqoj1JzcDzzNVHrIRw==} - peerDependencies: - '@nomicfoundation/hardhat-verify': ^2.0.1 - hardhat: ^2.18.0 - dependencies: - '@nomicfoundation/hardhat-verify': 2.0.12(hardhat@2.22.17) - '@nomicfoundation/ignition-core': 0.15.8 - '@nomicfoundation/ignition-ui': 0.15.8 - chalk: 4.1.2 - debug: 4.3.7(supports-color@8.1.1) - fs-extra: 10.1.0 - hardhat: 2.22.17(ts-node@10.9.2)(typescript@5.7.2) - json5: 2.2.3 - prompts: 2.4.2 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - dev: true - - /@nomicfoundation/hardhat-network-helpers@1.0.12(hardhat@2.22.17): - resolution: {integrity: sha512-xTNQNI/9xkHvjmCJnJOTyqDSl8uq1rKb2WOVmixQxFtRd7Oa3ecO8zM0cyC2YmOK+jHB9WPZ+F/ijkHg1CoORA==} - peerDependencies: - hardhat: ^2.9.5 - dependencies: - ethereumjs-util: 7.1.5 - hardhat: 2.22.17(ts-node@10.9.2)(typescript@5.7.2) - dev: true - - /@nomicfoundation/hardhat-toolbox@5.0.0(@nomicfoundation/hardhat-chai-matchers@2.0.8)(@nomicfoundation/hardhat-ethers@3.0.8)(@nomicfoundation/hardhat-ignition-ethers@0.15.8)(@nomicfoundation/hardhat-network-helpers@1.0.12)(@nomicfoundation/hardhat-verify@2.0.12)(@typechain/ethers-v6@0.5.1)(@typechain/hardhat@9.1.0)(@types/chai@4.3.20)(@types/mocha@10.0.10)(@types/node@18.19.67)(chai@4.5.0)(ethers@6.13.4)(hardhat-gas-reporter@1.0.10)(hardhat@2.22.17)(solidity-coverage@0.8.12)(ts-node@10.9.2)(typechain@8.3.2)(typescript@5.7.2): - resolution: {integrity: sha512-FnUtUC5PsakCbwiVNsqlXVIWG5JIb5CEZoSXbJUsEBun22Bivx2jhF1/q9iQbzuaGpJKFQyOhemPB2+XlEE6pQ==} - peerDependencies: - '@nomicfoundation/hardhat-chai-matchers': ^2.0.0 - '@nomicfoundation/hardhat-ethers': ^3.0.0 - '@nomicfoundation/hardhat-ignition-ethers': ^0.15.0 - '@nomicfoundation/hardhat-network-helpers': ^1.0.0 - '@nomicfoundation/hardhat-verify': ^2.0.0 - '@typechain/ethers-v6': ^0.5.0 - '@typechain/hardhat': ^9.0.0 - '@types/chai': ^4.2.0 - '@types/mocha': '>=9.1.0' - '@types/node': '>=18.0.0' - chai: ^4.2.0 - ethers: ^6.4.0 - hardhat: ^2.11.0 - hardhat-gas-reporter: ^1.0.8 - solidity-coverage: ^0.8.1 - ts-node: '>=8.0.0' - typechain: ^8.3.0 - typescript: '>=4.5.0' - dependencies: - '@nomicfoundation/hardhat-chai-matchers': 2.0.8(@nomicfoundation/hardhat-ethers@3.0.8)(chai@4.5.0)(ethers@6.13.4)(hardhat@2.22.17) - '@nomicfoundation/hardhat-ethers': 3.0.8(ethers@6.13.4)(hardhat@2.22.17) - '@nomicfoundation/hardhat-ignition-ethers': 0.15.8(@nomicfoundation/hardhat-ethers@3.0.8)(@nomicfoundation/hardhat-ignition@0.15.8)(@nomicfoundation/ignition-core@0.15.8)(ethers@6.13.4)(hardhat@2.22.17) - '@nomicfoundation/hardhat-network-helpers': 1.0.12(hardhat@2.22.17) - '@nomicfoundation/hardhat-verify': 2.0.12(hardhat@2.22.17) - '@typechain/ethers-v6': 0.5.1(ethers@6.13.4)(typechain@8.3.2)(typescript@5.7.2) - '@typechain/hardhat': 9.1.0(@typechain/ethers-v6@0.5.1)(ethers@6.13.4)(hardhat@2.22.17)(typechain@8.3.2) - '@types/chai': 4.3.20 - '@types/mocha': 10.0.10 - '@types/node': 18.19.67 - chai: 4.5.0 - ethers: 6.13.4 - hardhat: 2.22.17(ts-node@10.9.2)(typescript@5.7.2) - hardhat-gas-reporter: 1.0.10(hardhat@2.22.17) - solidity-coverage: 0.8.12(hardhat@2.22.17) - ts-node: 10.9.2(@types/node@18.19.67)(typescript@5.7.2) - typechain: 8.3.2(typescript@5.7.2) - typescript: 5.7.2 - dev: true - - /@nomicfoundation/hardhat-verify@2.0.12(hardhat@2.22.17): - resolution: {integrity: sha512-Lg3Nu7DCXASQRVI/YysjuAX2z8jwOCbS0w5tz2HalWGSTZThqA0v9N0v0psHbKNqzPJa8bNOeapIVSziyJTnAg==} - peerDependencies: - hardhat: ^2.0.4 - dependencies: - '@ethersproject/abi': 5.7.0 - '@ethersproject/address': 5.7.0 - cbor: 8.1.0 - debug: 4.3.7(supports-color@8.1.1) - hardhat: 2.22.17(ts-node@10.9.2)(typescript@5.7.2) - lodash.clonedeep: 4.5.0 - picocolors: 1.1.1 - semver: 6.3.1 - table: 6.8.2 - undici: 5.28.4 - transitivePeerDependencies: - - supports-color - dev: true - - /@nomicfoundation/ignition-core@0.15.8: - resolution: {integrity: sha512-U+CmTjKU9uwvh7qIabqboy/K/sDoClDgpsFRHoFvAj87DPDkXYb/mZBSkXPTU1wxTxrW6GTFE4lG3e7LAyF+kw==} - dependencies: - '@ethersproject/address': 5.6.1 - '@nomicfoundation/solidity-analyzer': 0.1.2 - cbor: 9.0.2 - debug: 4.3.7(supports-color@8.1.1) - ethers: 6.13.4 - fs-extra: 10.1.0 - immer: 10.0.2 - lodash: 4.17.21 - ndjson: 2.0.0 - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - dev: true - - /@nomicfoundation/ignition-ui@0.15.8: - resolution: {integrity: sha512-VUD5MsWrrv7E2P0AJO01pV8w8m66Du0uwBKXM0oUV5DRIzqm6eYHt9eCDb1KBINDpiFxOQiuyWQMdeKxgPp3qw==} - dev: true - - /@nomicfoundation/slang@0.18.3: - resolution: {integrity: sha512-YqAWgckqbHM0/CZxi9Nlf4hjk9wUNLC9ngWCWBiqMxPIZmzsVKYuChdlrfeBPQyvQQBoOhbx+7C1005kLVQDZQ==} - dependencies: - '@bytecodealliance/preview2-shim': 0.17.0 - dev: true - - /@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.2: - resolution: {integrity: sha512-JaqcWPDZENCvm++lFFGjrDd8mxtf+CtLd2MiXvMNTBD33dContTZ9TWETwNFwg7JTJT5Q9HEecH7FA+HTSsIUw==} - engines: {node: '>= 12'} - requiresBuild: true - dev: true - optional: true - - /@nomicfoundation/solidity-analyzer-darwin-x64@0.1.2: - resolution: {integrity: sha512-fZNmVztrSXC03e9RONBT+CiksSeYcxI1wlzqyr0L7hsQlK1fzV+f04g2JtQ1c/Fe74ZwdV6aQBdd6Uwl1052sw==} - engines: {node: '>= 12'} - requiresBuild: true - dev: true - optional: true - - /@nomicfoundation/solidity-analyzer-linux-arm64-gnu@0.1.2: - resolution: {integrity: sha512-3d54oc+9ZVBuB6nbp8wHylk4xh0N0Gc+bk+/uJae+rUgbOBwQSfuGIbAZt1wBXs5REkSmynEGcqx6DutoK0tPA==} - engines: {node: '>= 12'} - requiresBuild: true - dev: true - optional: true - - /@nomicfoundation/solidity-analyzer-linux-arm64-musl@0.1.2: - resolution: {integrity: sha512-iDJfR2qf55vgsg7BtJa7iPiFAsYf2d0Tv/0B+vhtnI16+wfQeTbP7teookbGvAo0eJo7aLLm0xfS/GTkvHIucA==} - engines: {node: '>= 12'} - requiresBuild: true - dev: true - optional: true - - /@nomicfoundation/solidity-analyzer-linux-x64-gnu@0.1.2: - resolution: {integrity: sha512-9dlHMAt5/2cpWyuJ9fQNOUXFB/vgSFORg1jpjX1Mh9hJ/MfZXlDdHQ+DpFCs32Zk5pxRBb07yGvSHk9/fezL+g==} - engines: {node: '>= 12'} - requiresBuild: true - dev: true - optional: true - - /@nomicfoundation/solidity-analyzer-linux-x64-musl@0.1.2: - resolution: {integrity: sha512-GzzVeeJob3lfrSlDKQw2bRJ8rBf6mEYaWY+gW0JnTDHINA0s2gPR4km5RLIj1xeZZOYz4zRw+AEeYgLRqB2NXg==} - engines: {node: '>= 12'} - requiresBuild: true - dev: true - optional: true - - /@nomicfoundation/solidity-analyzer-win32-x64-msvc@0.1.2: - resolution: {integrity: sha512-Fdjli4DCcFHb4Zgsz0uEJXZ2K7VEO+w5KVv7HmT7WO10iODdU9csC2az4jrhEsRtiR9Gfd74FlG0NYlw1BMdyA==} - engines: {node: '>= 12'} - requiresBuild: true - dev: true - optional: true - - /@nomicfoundation/solidity-analyzer@0.1.2: - resolution: {integrity: sha512-q4n32/FNKIhQ3zQGGw5CvPF6GTvDCpYwIf7bEY/dZTZbgfDsHyjJwURxUJf3VQuuJj+fDIFl4+KkBVbw4Ef6jA==} - engines: {node: '>= 12'} - optionalDependencies: - '@nomicfoundation/solidity-analyzer-darwin-arm64': 0.1.2 - '@nomicfoundation/solidity-analyzer-darwin-x64': 0.1.2 - '@nomicfoundation/solidity-analyzer-linux-arm64-gnu': 0.1.2 - '@nomicfoundation/solidity-analyzer-linux-arm64-musl': 0.1.2 - '@nomicfoundation/solidity-analyzer-linux-x64-gnu': 0.1.2 - '@nomicfoundation/solidity-analyzer-linux-x64-musl': 0.1.2 - '@nomicfoundation/solidity-analyzer-win32-x64-msvc': 0.1.2 - dev: true - - /@npmcli/fs@1.1.1: - resolution: {integrity: sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==} - requiresBuild: true - dependencies: - '@gar/promisify': 1.1.3 - semver: 7.6.3 - optional: true - - /@npmcli/move-file@1.1.2: - resolution: {integrity: sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==} - engines: {node: '>=10'} - deprecated: This functionality has been moved to @npmcli/fs - requiresBuild: true - dependencies: - mkdirp: 1.0.4 - rimraf: 3.0.2 - optional: true - - /@openzeppelin/contracts-upgradeable@5.0.2(@openzeppelin/contracts@5.0.2): - resolution: {integrity: sha512-0MmkHSHiW2NRFiT9/r5Lu4eJq5UJ4/tzlOgYXNAIj/ONkQTVnz22pLxDvp4C4uZ9he7ZFvGn3Driptn1/iU7tQ==} - peerDependencies: - '@openzeppelin/contracts': 5.0.2 - dependencies: - '@openzeppelin/contracts': 5.0.2 - dev: false - - /@openzeppelin/contracts@5.0.2: - resolution: {integrity: sha512-ytPc6eLGcHHnapAZ9S+5qsdomhjo6QBHTDRRBFfTxXIpsicMhVPouPgmUPebZZZGX7vt9USA+Z+0M0dSVtSUEA==} - dev: false - - /@openzeppelin/contracts@5.1.0: - resolution: {integrity: sha512-p1ULhl7BXzjjbha5aqst+QMLY+4/LCWADXOCsmLHRM77AqiPjnd9vvUN9sosUfhL9JGKpZ0TjEGxgvnizmWGSA==} - dev: true - - /@openzeppelin/defender-sdk-base-client@1.15.2: - resolution: {integrity: sha512-N3ZTeH8TXyklL7yNPMLUv0dxQwT78DTkOEDhzMS2/QE2FxbXrclSseoeeXxl6UYI61RBtZKn+okbSsbwiB5QWQ==} - dependencies: - amazon-cognito-identity-js: 6.3.12 - async-retry: 1.3.3 - transitivePeerDependencies: - - encoding - dev: true - - /@openzeppelin/defender-sdk-deploy-client@1.15.2(debug@4.3.7): - resolution: {integrity: sha512-zspzMqh+OC8arXAkgBqTUDVO+NfCkt54UrsmQHbA3UAjr5TiDXKycBKU5ORb01hE+2gAmoPwEpDW9uS2VLg33A==} - dependencies: - '@openzeppelin/defender-sdk-base-client': 1.15.2 - axios: 1.7.8(debug@4.3.7) - lodash: 4.17.21 - transitivePeerDependencies: - - debug - - encoding - dev: true - - /@openzeppelin/defender-sdk-network-client@1.15.2(debug@4.3.7): - resolution: {integrity: sha512-9r9pegc1aR7xzP9fmj1zvkk0OXMRJE10JabxxiJzAQQgmNXDeTGI6W5bFgrNJfxzcImNGqddJ3K4weKdLyL21A==} - dependencies: - '@openzeppelin/defender-sdk-base-client': 1.15.2 - axios: 1.7.8(debug@4.3.7) - lodash: 4.17.21 - transitivePeerDependencies: - - debug - - encoding - dev: true - - /@openzeppelin/hardhat-upgrades@3.6.0(@nomicfoundation/hardhat-ethers@3.0.8)(@nomicfoundation/hardhat-verify@2.0.12)(ethers@6.13.4)(hardhat@2.22.17): - resolution: {integrity: sha512-RuVuCciCfFOqCyKSJ2D4Zffp3hxhvXTn16JzTlD9cx3A7V/2d3JA75tpRHD7RVPic+dcSFIf+BZRWOHuhc2ayg==} - hasBin: true - peerDependencies: - '@nomicfoundation/hardhat-ethers': ^3.0.0 - '@nomicfoundation/hardhat-verify': ^2.0.0 - ethers: ^6.6.0 - hardhat: ^2.0.2 - peerDependenciesMeta: - '@nomicfoundation/hardhat-verify': - optional: true - dependencies: - '@nomicfoundation/hardhat-ethers': 3.0.8(ethers@6.13.4)(hardhat@2.22.17) - '@nomicfoundation/hardhat-verify': 2.0.12(hardhat@2.22.17) - '@openzeppelin/defender-sdk-base-client': 1.15.2 - '@openzeppelin/defender-sdk-deploy-client': 1.15.2(debug@4.3.7) - '@openzeppelin/defender-sdk-network-client': 1.15.2(debug@4.3.7) - '@openzeppelin/upgrades-core': 1.41.0 - chalk: 4.1.2 - debug: 4.3.7(supports-color@8.1.1) - ethereumjs-util: 7.1.5 - ethers: 6.13.4 - hardhat: 2.22.17(ts-node@10.9.2)(typescript@5.7.2) - proper-lockfile: 4.1.2 - undici: 6.21.0 - transitivePeerDependencies: - - encoding - - supports-color - dev: true - - /@openzeppelin/upgrades-core@1.41.0: - resolution: {integrity: sha512-+oryinqZnxkiZvg7bWqWX4Ki/CNwVUZEqC6Elpi5PQoahpL3/6Sq9xjIozD5AiI2O61h8JHQ+A//5NtczyavJw==} - hasBin: true - dependencies: - '@nomicfoundation/slang': 0.18.3 - cbor: 9.0.2 - chalk: 4.1.2 - compare-versions: 6.1.1 - debug: 4.3.7(supports-color@8.1.1) - ethereumjs-util: 7.1.5 - minimatch: 9.0.5 - minimist: 1.2.8 - proper-lockfile: 4.1.2 - solidity-ast: 0.4.59 - transitivePeerDependencies: - - supports-color - dev: true - - /@scure/base@1.1.9: - resolution: {integrity: sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==} - dev: true - - /@scure/bip32@1.1.5: - resolution: {integrity: sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw==} - dependencies: - '@noble/hashes': 1.2.0 - '@noble/secp256k1': 1.7.1 - '@scure/base': 1.1.9 - dev: true - - /@scure/bip32@1.4.0: - resolution: {integrity: sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==} - dependencies: - '@noble/curves': 1.4.2 - '@noble/hashes': 1.4.0 - '@scure/base': 1.1.9 - dev: true - - /@scure/bip39@1.1.1: - resolution: {integrity: sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg==} - dependencies: - '@noble/hashes': 1.2.0 - '@scure/base': 1.1.9 - dev: true - - /@scure/bip39@1.3.0: - resolution: {integrity: sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==} - dependencies: - '@noble/hashes': 1.4.0 - '@scure/base': 1.1.9 - dev: true - - /@sentry/core@5.30.0: - resolution: {integrity: sha512-TmfrII8w1PQZSZgPpUESqjB+jC6MvZJZdLtE/0hZ+SrnKhW3x5WlYLvTXZpcWePYBku7rl2wn1RZu6uT0qCTeg==} - engines: {node: '>=6'} - dependencies: - '@sentry/hub': 5.30.0 - '@sentry/minimal': 5.30.0 - '@sentry/types': 5.30.0 - '@sentry/utils': 5.30.0 - tslib: 1.14.1 - dev: true - - /@sentry/hub@5.30.0: - resolution: {integrity: sha512-2tYrGnzb1gKz2EkMDQcfLrDTvmGcQPuWxLnJKXJvYTQDGLlEvi2tWz1VIHjunmOvJrB5aIQLhm+dcMRwFZDCqQ==} - engines: {node: '>=6'} - dependencies: - '@sentry/types': 5.30.0 - '@sentry/utils': 5.30.0 - tslib: 1.14.1 - dev: true - - /@sentry/minimal@5.30.0: - resolution: {integrity: sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw==} - engines: {node: '>=6'} - dependencies: - '@sentry/hub': 5.30.0 - '@sentry/types': 5.30.0 - tslib: 1.14.1 - dev: true - - /@sentry/node@5.30.0: - resolution: {integrity: sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg==} - engines: {node: '>=6'} - dependencies: - '@sentry/core': 5.30.0 - '@sentry/hub': 5.30.0 - '@sentry/tracing': 5.30.0 - '@sentry/types': 5.30.0 - '@sentry/utils': 5.30.0 - cookie: 0.4.2 - https-proxy-agent: 5.0.1 - lru_map: 0.3.3 - tslib: 1.14.1 - transitivePeerDependencies: - - supports-color - dev: true - - /@sentry/tracing@5.30.0: - resolution: {integrity: sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw==} - engines: {node: '>=6'} - dependencies: - '@sentry/hub': 5.30.0 - '@sentry/minimal': 5.30.0 - '@sentry/types': 5.30.0 - '@sentry/utils': 5.30.0 - tslib: 1.14.1 - dev: true - - /@sentry/types@5.30.0: - resolution: {integrity: sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw==} - engines: {node: '>=6'} - dev: true - - /@sentry/utils@5.30.0: - resolution: {integrity: sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww==} - engines: {node: '>=6'} - dependencies: - '@sentry/types': 5.30.0 - tslib: 1.14.1 - dev: true - - /@sinclair/typebox@0.27.8: - resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} - dev: true - - /@sinonjs/commons@3.0.1: - resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} - dependencies: - type-detect: 4.0.8 - dev: true - - /@sinonjs/fake-timers@10.3.0: - resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==} - dependencies: - '@sinonjs/commons': 3.0.1 - dev: true - - /@smithy/types@3.7.1: - resolution: {integrity: sha512-XKLcLXZY7sUQgvvWyeaL/qwNPp6V3dWcUjqrQKjSb+tzYiCy340R/c64LV5j+Tnb2GhmunEX0eou+L+m2hJNYA==} - engines: {node: '>=16.0.0'} - dependencies: - tslib: 2.8.1 - dev: true - - /@solidity-parser/parser@0.14.5: - resolution: {integrity: sha512-6dKnHZn7fg/iQATVEzqyUOyEidbn05q7YA2mQ9hC0MMXhhV3/JrsxmFSYZAcr7j1yUP700LLhTruvJ3MiQmjJg==} - dependencies: - antlr4ts: 0.5.0-alpha.4 - dev: true - - /@solidity-parser/parser@0.16.2: - resolution: {integrity: sha512-PI9NfoA3P8XK2VBkK5oIfRgKDsicwDZfkVq9ZTBCQYGOP1N2owgY2dyLGyU5/J/hQs8KRk55kdmvTLjy3Mu3vg==} - dependencies: - antlr4ts: 0.5.0-alpha.4 - dev: true - - /@solidity-parser/parser@0.18.0: - resolution: {integrity: sha512-yfORGUIPgLck41qyN7nbwJRAx17/jAIXCTanHOJZhB6PJ1iAk/84b/xlsVKFSyNyLXIj0dhppoE0+CRws7wlzA==} - dev: true - - /@tootallnate/once@1.1.2: - resolution: {integrity: sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==} - engines: {node: '>= 6'} - requiresBuild: true - optional: true - - /@trivago/prettier-plugin-sort-imports@4.3.0(prettier@2.8.8): - resolution: {integrity: sha512-r3n0onD3BTOVUNPhR4lhVK4/pABGpbA7bW3eumZnYdKaHkf1qEC+Mag6DPbGNuuh0eG8AaYj+YqmVHSiGslaTQ==} - peerDependencies: - '@vue/compiler-sfc': 3.x - prettier: 2.x - 3.x - peerDependenciesMeta: - '@vue/compiler-sfc': - optional: true - dependencies: - '@babel/generator': 7.17.7 - '@babel/parser': 7.26.2 - '@babel/traverse': 7.23.2 - '@babel/types': 7.17.0 - javascript-natural-sort: 0.7.1 - lodash: 4.17.21 - prettier: 2.8.8 - transitivePeerDependencies: - - supports-color - dev: true - - /@tsconfig/node10@1.0.11: - resolution: {integrity: sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==} - dev: true - - /@tsconfig/node12@1.0.11: - resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} - dev: true - - /@tsconfig/node14@1.0.3: - resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} - dev: true - - /@tsconfig/node16@1.0.4: - resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} - dev: true - - /@typechain/ethers-v6@0.5.1(ethers@6.13.4)(typechain@8.3.2)(typescript@5.7.2): - resolution: {integrity: sha512-F+GklO8jBWlsaVV+9oHaPh5NJdd6rAKN4tklGfInX1Q7h0xPgVLP39Jl3eCulPB5qexI71ZFHwbljx4ZXNfouA==} - peerDependencies: - ethers: 6.x - typechain: ^8.3.2 - typescript: '>=4.7.0' - dependencies: - ethers: 6.13.4 - lodash: 4.17.21 - ts-essentials: 7.0.3(typescript@5.7.2) - typechain: 8.3.2(typescript@5.7.2) - typescript: 5.7.2 - dev: true - - /@typechain/hardhat@9.1.0(@typechain/ethers-v6@0.5.1)(ethers@6.13.4)(hardhat@2.22.17)(typechain@8.3.2): - resolution: {integrity: sha512-mtaUlzLlkqTlfPwB3FORdejqBskSnh+Jl8AIJGjXNAQfRQ4ofHADPl1+oU7Z3pAJzmZbUXII8MhOLQltcHgKnA==} - peerDependencies: - '@typechain/ethers-v6': ^0.5.1 - ethers: ^6.1.0 - hardhat: ^2.9.9 - typechain: ^8.3.2 - dependencies: - '@typechain/ethers-v6': 0.5.1(ethers@6.13.4)(typechain@8.3.2)(typescript@5.7.2) - ethers: 6.13.4 - fs-extra: 9.1.0 - hardhat: 2.22.17(ts-node@10.9.2)(typescript@5.7.2) - typechain: 8.3.2(typescript@5.7.2) - dev: true - - /@types/babel__core@7.20.5: - resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} - dependencies: - '@babel/parser': 7.26.3 - '@babel/types': 7.26.3 - '@types/babel__generator': 7.6.8 - '@types/babel__template': 7.4.4 - '@types/babel__traverse': 7.20.6 - dev: true - - /@types/babel__generator@7.6.8: - resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==} - dependencies: - '@babel/types': 7.26.3 - dev: true - - /@types/babel__template@7.4.4: - resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} - dependencies: - '@babel/parser': 7.26.3 - '@babel/types': 7.26.3 - dev: true - - /@types/babel__traverse@7.20.6: - resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==} - dependencies: - '@babel/types': 7.26.3 - dev: true - - /@types/bn.js@4.11.6: - resolution: {integrity: sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==} - dependencies: - '@types/node': 18.19.67 - dev: true - - /@types/bn.js@5.1.6: - resolution: {integrity: sha512-Xh8vSwUeMKeYYrj3cX4lGQgFSF/N03r+tv4AiLl1SucqV+uTQpxRcnM8AkXKHwYP9ZPXOYXRr2KPXpVlIvqh9w==} - dependencies: - '@types/node': 18.19.67 - dev: true - - /@types/chai-as-promised@7.1.8: - resolution: {integrity: sha512-ThlRVIJhr69FLlh6IctTXFkmhtP3NpMZ2QGq69StYLyKZFp/HOp1VdKZj7RvfNWYYcJ1xlbLGLLWj1UvP5u/Gw==} - dependencies: - '@types/chai': 4.3.20 - dev: true - - /@types/chai@4.3.20: - resolution: {integrity: sha512-/pC9HAB5I/xMlc5FP77qjCnI16ChlJfW0tGa0IUcFn38VJrTV6DeZ60NU5KZBtaOZqjdpwTWohz5HU1RrhiYxQ==} - dev: true - - /@types/concat-stream@1.6.1: - resolution: {integrity: sha512-eHE4cQPoj6ngxBZMvVf6Hw7Mh4jMW4U9lpGmS5GBPB9RYxlFg+CHaVN7ErNY4W9XfLIEn20b4VDYaIrbq0q4uA==} - dependencies: - '@types/node': 18.19.67 - dev: true - - /@types/eslint@9.6.1: - resolution: {integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==} - dependencies: - '@types/estree': 1.0.6 - '@types/json-schema': 7.0.15 - dev: true - - /@types/eslint__js@8.42.3: - resolution: {integrity: sha512-alfG737uhmPdnvkrLdZLcEKJ/B8s9Y4hrZ+YAdzUeoArBlSUERA2E87ROfOaS4jd/C45fzOoZzidLc1IPwLqOw==} - dependencies: - '@types/eslint': 9.6.1 - dev: true - - /@types/estree@1.0.6: - resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} - dev: true - - /@types/form-data@0.0.33: - resolution: {integrity: sha512-8BSvG1kGm83cyJITQMZSulnl6QV8jqAGreJsc5tPu1Jq0vTSOiY/k24Wx82JRpWwZSqrala6sd5rWi6aNXvqcw==} - dependencies: - '@types/node': 18.19.67 - dev: true - - /@types/fs-extra@9.0.13: - resolution: {integrity: sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==} - dependencies: - '@types/node': 18.19.67 - dev: true - - /@types/glob-to-regexp@0.4.4: - resolution: {integrity: sha512-nDKoaKJYbnn1MZxUY0cA1bPmmgZbg0cTq7Rh13d0KWYNOiKbqoR+2d89SnRPszGh7ROzSwZ/GOjZ4jPbmmZ6Eg==} - dev: true - - /@types/glob@7.2.0: - resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} - dependencies: - '@types/minimatch': 5.1.2 - '@types/node': 18.19.67 - dev: true - - /@types/graceful-fs@4.1.9: - resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} - dependencies: - '@types/node': 18.19.67 - dev: true - - /@types/istanbul-lib-coverage@2.0.6: - resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} - dev: true - - /@types/istanbul-lib-report@3.0.3: - resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} - dependencies: - '@types/istanbul-lib-coverage': 2.0.6 - dev: true - - /@types/istanbul-reports@3.0.4: - resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} - dependencies: - '@types/istanbul-lib-report': 3.0.3 - dev: true - - /@types/jest@29.5.14: - resolution: {integrity: sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==} - dependencies: - expect: 29.7.0 - pretty-format: 29.7.0 - dev: true - - /@types/json-schema@7.0.15: - resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} - dev: true - - /@types/lru-cache@5.1.1: - resolution: {integrity: sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==} - dev: true - - /@types/minimatch@5.1.2: - resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} - dev: true - - /@types/mkdirp@0.5.2: - resolution: {integrity: sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg==} - dependencies: - '@types/node': 18.19.67 - dev: true - - /@types/mocha@10.0.10: - resolution: {integrity: sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q==} - dev: true - - /@types/node@10.17.60: - resolution: {integrity: sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==} - dev: true - - /@types/node@18.19.67: - resolution: {integrity: sha512-wI8uHusga+0ZugNp0Ol/3BqQfEcCCNfojtO6Oou9iVNGPTL6QNSdnUdqq85fRgIorLhLMuPIKpsN98QE9Nh+KQ==} - dependencies: - undici-types: 5.26.5 - dev: true - - /@types/node@22.7.5: - resolution: {integrity: sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==} - dependencies: - undici-types: 6.19.8 - dev: true - - /@types/node@8.10.66: - resolution: {integrity: sha512-tktOkFUA4kXx2hhhrB8bIFb5TbwzS4uOhKEmwiD+NoiL0qtP2OQ9mFldbgD4dV1djrlBYP6eBuQZiWjuHUpqFw==} - dev: true - - /@types/pbkdf2@3.1.2: - resolution: {integrity: sha512-uRwJqmiXmh9++aSu1VNEn3iIxWOhd8AHXNSdlaLfdAAdSTY9jYVeGWnzejM3dvrkbqE3/hyQkQQ29IFATEGlew==} - dependencies: - '@types/node': 18.19.67 - dev: true - - /@types/prettier@2.7.3: - resolution: {integrity: sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==} - dev: true - - /@types/qs@6.9.17: - resolution: {integrity: sha512-rX4/bPcfmvxHDv0XjfJELTTr+iB+tn032nPILqHm5wbthUUUuVtNGGqzhya9XUxjTP8Fpr0qYgSZZKxGY++svQ==} - dev: true - - /@types/resolve@0.0.8: - resolution: {integrity: sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==} - dependencies: - '@types/node': 18.19.67 - dev: true - - /@types/secp256k1@4.0.6: - resolution: {integrity: sha512-hHxJU6PAEUn0TP4S/ZOzuTUvJWuZ6eIKeNKb5RBpODvSl6hp1Wrw4s7ATY50rklRCScUDpHzVA/DQdSjJ3UoYQ==} - dependencies: - '@types/node': 18.19.67 - dev: true - - /@types/stack-utils@2.0.3: - resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} - dev: true - - /@types/yargs-parser@21.0.3: - resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} - dev: true - - /@types/yargs@17.0.33: - resolution: {integrity: sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==} - dependencies: - '@types/yargs-parser': 21.0.3 - dev: true - - /@typescript-eslint/eslint-plugin@8.17.0(@typescript-eslint/parser@8.17.0)(eslint@9.16.0)(typescript@5.7.2): - resolution: {integrity: sha512-HU1KAdW3Tt8zQkdvNoIijfWDMvdSweFYm4hWh+KwhPstv+sCmWb89hCIP8msFm9N1R/ooh9honpSuvqKWlYy3w==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 - eslint: ^8.57.0 || ^9.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.17.0(eslint@9.16.0)(typescript@5.7.2) - '@typescript-eslint/scope-manager': 8.17.0 - '@typescript-eslint/type-utils': 8.17.0(eslint@9.16.0)(typescript@5.7.2) - '@typescript-eslint/utils': 8.17.0(eslint@9.16.0)(typescript@5.7.2) - '@typescript-eslint/visitor-keys': 8.17.0 - eslint: 9.16.0 - graphemer: 1.4.0 - ignore: 5.3.2 - natural-compare: 1.4.0 - ts-api-utils: 1.4.3(typescript@5.7.2) - typescript: 5.7.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/parser@8.17.0(eslint@9.16.0)(typescript@5.7.2): - resolution: {integrity: sha512-Drp39TXuUlD49F7ilHHCG7TTg8IkA+hxCuULdmzWYICxGXvDXmDmWEjJYZQYgf6l/TFfYNE167m7isnc3xlIEg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/scope-manager': 8.17.0 - '@typescript-eslint/types': 8.17.0 - '@typescript-eslint/typescript-estree': 8.17.0(typescript@5.7.2) - '@typescript-eslint/visitor-keys': 8.17.0 - debug: 4.3.7(supports-color@8.1.1) - eslint: 9.16.0 - typescript: 5.7.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/scope-manager@8.17.0: - resolution: {integrity: sha512-/ewp4XjvnxaREtqsZjF4Mfn078RD/9GmiEAtTeLQ7yFdKnqwTOgRMSvFz4et9U5RiJQ15WTGXPLj89zGusvxBg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - dependencies: - '@typescript-eslint/types': 8.17.0 - '@typescript-eslint/visitor-keys': 8.17.0 - dev: true - - /@typescript-eslint/type-utils@8.17.0(eslint@9.16.0)(typescript@5.7.2): - resolution: {integrity: sha512-q38llWJYPd63rRnJ6wY/ZQqIzPrBCkPdpIsaCfkR3Q4t3p6sb422zougfad4TFW9+ElIFLVDzWGiGAfbb/v2qw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/typescript-estree': 8.17.0(typescript@5.7.2) - '@typescript-eslint/utils': 8.17.0(eslint@9.16.0)(typescript@5.7.2) - debug: 4.3.7(supports-color@8.1.1) - eslint: 9.16.0 - ts-api-utils: 1.4.3(typescript@5.7.2) - typescript: 5.7.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/types@8.17.0: - resolution: {integrity: sha512-gY2TVzeve3z6crqh2Ic7Cr+CAv6pfb0Egee7J5UAVWCpVvDI/F71wNfolIim4FE6hT15EbpZFVUj9j5i38jYXA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - dev: true - - /@typescript-eslint/typescript-estree@8.17.0(typescript@5.7.2): - resolution: {integrity: sha512-JqkOopc1nRKZpX+opvKqnM3XUlM7LpFMD0lYxTqOTKQfCWAmxw45e3qlOCsEqEB2yuacujivudOFpCnqkBDNMw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/types': 8.17.0 - '@typescript-eslint/visitor-keys': 8.17.0 - debug: 4.3.7(supports-color@8.1.1) - fast-glob: 3.3.2 - is-glob: 4.0.3 - minimatch: 9.0.5 - semver: 7.6.3 - ts-api-utils: 1.4.3(typescript@5.7.2) - typescript: 5.7.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/utils@8.17.0(eslint@9.16.0)(typescript@5.7.2): - resolution: {integrity: sha512-bQC8BnEkxqG8HBGKwG9wXlZqg37RKSMY7v/X8VEWD8JG2JuTHuNK0VFvMPMUKQcbk6B+tf05k+4AShAEtCtJ/w==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@eslint-community/eslint-utils': 4.4.1(eslint@9.16.0) - '@typescript-eslint/scope-manager': 8.17.0 - '@typescript-eslint/types': 8.17.0 - '@typescript-eslint/typescript-estree': 8.17.0(typescript@5.7.2) - eslint: 9.16.0 - typescript: 5.7.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@typescript-eslint/visitor-keys@8.17.0: - resolution: {integrity: sha512-1Hm7THLpO6ww5QU6H/Qp+AusUUl+z/CAm3cNZZ0jQvon9yicgO7Rwd+/WWRpMKLYV6p2UvdbR27c86rzCPpreg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - dependencies: - '@typescript-eslint/types': 8.17.0 - eslint-visitor-keys: 4.2.0 - dev: true - - /abbrev@1.0.9: - resolution: {integrity: sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q==} - dev: true - - /abbrev@1.1.1: - resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} - requiresBuild: true - optional: true - - /acorn-jsx@5.3.2(acorn@8.14.0): - resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} - peerDependencies: - acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - dependencies: - acorn: 8.14.0 - dev: true - - /acorn-walk@8.3.4: - resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==} - engines: {node: '>=0.4.0'} - dependencies: - acorn: 8.14.0 - dev: true - - /acorn@8.14.0: - resolution: {integrity: sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==} - engines: {node: '>=0.4.0'} - hasBin: true - dev: true - - /adm-zip@0.4.16: - resolution: {integrity: sha512-TFi4HBKSGfIKsK5YCkKaaFG2m4PEDyViZmEwof3MTIgzimHLto6muaHVpbrljdIvIrFZzEq/p4nafOeLcYegrg==} - engines: {node: '>=0.3.0'} - dev: true - - /aes-js@3.0.0: - resolution: {integrity: sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==} - dev: true - - /aes-js@4.0.0-beta.5: - resolution: {integrity: sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==} - dev: true - - /agent-base@6.0.2: - resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} - engines: {node: '>= 6.0.0'} - dependencies: - debug: 4.3.7(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - - /agentkeepalive@4.5.0: - resolution: {integrity: sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==} - engines: {node: '>= 8.0.0'} - requiresBuild: true - dependencies: - humanize-ms: 1.2.1 - optional: true - - /aggregate-error@3.1.0: - resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} - engines: {node: '>=8'} - dependencies: - clean-stack: 2.2.0 - indent-string: 4.0.0 - - /ajv@6.12.6: - resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} - dependencies: - fast-deep-equal: 3.1.3 - fast-json-stable-stringify: 2.1.0 - json-schema-traverse: 0.4.1 - uri-js: 4.4.1 - dev: true - - /ajv@8.17.1: - resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} - dependencies: - fast-deep-equal: 3.1.3 - fast-uri: 3.0.3 - json-schema-traverse: 1.0.0 - require-from-string: 2.0.2 - dev: true - - /amazon-cognito-identity-js@6.3.12: - resolution: {integrity: sha512-s7NKDZgx336cp+oDeUtB2ZzT8jWJp/v2LWuYl+LQtMEODe22RF1IJ4nRiDATp+rp1pTffCZcm44Quw4jx2bqNg==} - dependencies: - '@aws-crypto/sha256-js': 1.2.2 - buffer: 4.9.2 - fast-base64-decode: 1.0.0 - isomorphic-unfetch: 3.1.0 - js-cookie: 2.2.1 - transitivePeerDependencies: - - encoding - dev: true - - /amdefine@1.0.1: - resolution: {integrity: sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==} - engines: {node: '>=0.4.2'} - requiresBuild: true - dev: true - optional: true - - /ansi-align@3.0.1: - resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} - dependencies: - string-width: 4.2.3 - dev: true - - /ansi-colors@4.1.3: - resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} - engines: {node: '>=6'} - dev: true - - /ansi-escapes@4.3.2: - resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} - engines: {node: '>=8'} - dependencies: - type-fest: 0.21.3 - dev: true - - /ansi-regex@3.0.1: - resolution: {integrity: sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==} - engines: {node: '>=4'} - dev: true - - /ansi-regex@5.0.1: - resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} - engines: {node: '>=8'} - - /ansi-styles@3.2.1: - resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} - engines: {node: '>=4'} - dependencies: - color-convert: 1.9.3 - dev: true - - /ansi-styles@4.3.0: - resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} - engines: {node: '>=8'} - dependencies: - color-convert: 2.0.1 - dev: true - - /ansi-styles@5.2.0: - resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} - engines: {node: '>=10'} - dev: true - - /antlr4@4.13.2: - resolution: {integrity: sha512-QiVbZhyy4xAZ17UPEuG3YTOt8ZaoeOR1CvEAqrEsDBsOqINslaB147i9xqljZqoyf5S+EUlGStaj+t22LT9MOg==} - engines: {node: '>=16'} - dev: true - - /antlr4ts@0.5.0-alpha.4: - resolution: {integrity: sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==} - dev: true - - /anymatch@3.1.3: - resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} - engines: {node: '>= 8'} - dependencies: - normalize-path: 3.0.0 - picomatch: 2.3.1 - dev: true - - /aproba@2.0.0: - resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} - requiresBuild: true - optional: true - - /are-we-there-yet@3.0.1: - resolution: {integrity: sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - deprecated: This package is no longer supported. - requiresBuild: true - dependencies: - delegates: 1.0.0 - readable-stream: 3.6.2 - optional: true - - /arg@4.1.3: - resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} - dev: true - - /argparse@1.0.10: - resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} - dependencies: - sprintf-js: 1.0.3 - dev: true - - /argparse@2.0.1: - resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - dev: true - - /array-back@3.1.0: - resolution: {integrity: sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==} - engines: {node: '>=6'} - dev: true - - /array-back@4.0.2: - resolution: {integrity: sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==} - engines: {node: '>=8'} - dev: true - - /array-union@2.1.0: - resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} - engines: {node: '>=8'} - dev: true - - /array-uniq@1.0.3: - resolution: {integrity: sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==} - engines: {node: '>=0.10.0'} - dev: true - - /asap@2.0.6: - resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} - dev: true - - /assertion-error@1.1.0: - resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} - dev: true - - /ast-parents@0.0.1: - resolution: {integrity: sha512-XHusKxKz3zoYk1ic8Un640joHbFMhbqneyoZfoKnEGtf2ey9Uh/IdpcQplODdO/kENaMIWsD0nJm4+wX3UNLHA==} - dev: true - - /astral-regex@2.0.0: - resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==} - engines: {node: '>=8'} - dev: true - - /async-retry@1.3.3: - resolution: {integrity: sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==} - dependencies: - retry: 0.13.1 - dev: true - - /async@1.5.2: - resolution: {integrity: sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==} - dev: true - - /async@3.2.6: - resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} - dev: true - - /asynckit@0.4.0: - resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} - dev: true - - /at-least-node@1.0.0: - resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} - engines: {node: '>= 4.0.0'} - dev: true - - /available-typed-arrays@1.0.7: - resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} - engines: {node: '>= 0.4'} - dependencies: - possible-typed-array-names: 1.0.0 - dev: true - - /axios@0.21.4(debug@4.3.7): - resolution: {integrity: sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==} - dependencies: - follow-redirects: 1.15.9(debug@4.3.7) - transitivePeerDependencies: - - debug - dev: true - - /axios@1.7.8(debug@4.3.7): - resolution: {integrity: sha512-Uu0wb7KNqK2t5K+YQyVCLM76prD5sRFjKHbJYCP1J7JFGEQ6nN7HWn9+04LAeiJ3ji54lgS/gZCH1oxyrf1SPw==} - dependencies: - follow-redirects: 1.15.9(debug@4.3.7) - form-data: 4.0.1 - proxy-from-env: 1.1.0 - transitivePeerDependencies: - - debug - dev: true - - /babel-jest@29.7.0(@babel/core@7.26.0): - resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - '@babel/core': ^7.8.0 - dependencies: - '@babel/core': 7.26.0 - '@jest/transform': 29.7.0 - '@types/babel__core': 7.20.5 - babel-plugin-istanbul: 6.1.1 - babel-preset-jest: 29.6.3(@babel/core@7.26.0) - chalk: 4.1.2 - graceful-fs: 4.2.11 - slash: 3.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /babel-plugin-istanbul@6.1.1: - resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} - engines: {node: '>=8'} - dependencies: - '@babel/helper-plugin-utils': 7.25.9 - '@istanbuljs/load-nyc-config': 1.1.0 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-instrument: 5.2.1 - test-exclude: 6.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /babel-plugin-jest-hoist@29.6.3: - resolution: {integrity: sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@babel/template': 7.25.9 - '@babel/types': 7.26.3 - '@types/babel__core': 7.20.5 - '@types/babel__traverse': 7.20.6 - dev: true - - /babel-preset-current-node-syntax@1.1.0(@babel/core@7.26.0): - resolution: {integrity: sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.26.0 - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.26.0) - '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.26.0) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.26.0) - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.26.0) - '@babel/plugin-syntax-import-attributes': 7.26.0(@babel/core@7.26.0) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.26.0) - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.26.0) - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.26.0) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.26.0) - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.26.0) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.26.0) - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.26.0) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.26.0) - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.26.0) - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.26.0) - dev: true - - /babel-preset-jest@29.6.3(@babel/core@7.26.0): - resolution: {integrity: sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.26.0 - babel-plugin-jest-hoist: 29.6.3 - babel-preset-current-node-syntax: 1.1.0(@babel/core@7.26.0) - dev: true - - /balanced-match@1.0.2: - resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} - - /base-x@3.0.10: - resolution: {integrity: sha512-7d0s06rR9rYaIWHkpfLIFICM/tkSVdoPC9qYAQRpxn9DdKNWNsKC0uk++akckyLq16Tx2WIinnZ6WRriAt6njQ==} - dependencies: - safe-buffer: 5.2.1 - dev: true - - /base64-js@1.5.1: - resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - - /bech32@1.1.4: - resolution: {integrity: sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==} - dev: true - - /bigint-buffer@1.1.5: - resolution: {integrity: sha512-trfYco6AoZ+rKhKnxA0hgX0HAbVP/s808/EuDSe2JDzUnCp/xAsli35Orvk67UrTEcwuxZqYZDmfA2RXJgxVvA==} - engines: {node: '>= 10.0.0'} - requiresBuild: true - dependencies: - bindings: 1.5.0 - - /binary-extensions@2.3.0: - resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} - engines: {node: '>=8'} - dev: true - - /bindings@1.5.0: - resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} - dependencies: - file-uri-to-path: 1.0.0 - - /bl@4.1.0: - resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} - dependencies: - buffer: 5.7.1 - inherits: 2.0.4 - readable-stream: 3.6.2 - - /blakejs@1.2.1: - resolution: {integrity: sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==} - dev: true - - /bn.js@4.11.6: - resolution: {integrity: sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA==} - dev: true - - /bn.js@4.12.1: - resolution: {integrity: sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==} - dev: true - - /bn.js@5.2.1: - resolution: {integrity: sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==} - dev: true - - /boxen@5.1.2: - resolution: {integrity: sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ==} - engines: {node: '>=10'} - dependencies: - ansi-align: 3.0.1 - camelcase: 6.3.0 - chalk: 4.1.2 - cli-boxes: 2.2.1 - string-width: 4.2.3 - type-fest: 0.20.2 - widest-line: 3.1.0 - wrap-ansi: 7.0.0 - dev: true - - /brace-expansion@1.1.11: - resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} - dependencies: - balanced-match: 1.0.2 - concat-map: 0.0.1 - - /brace-expansion@2.0.1: - resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} - dependencies: - balanced-match: 1.0.2 - dev: true - - /braces@3.0.3: - resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} - engines: {node: '>=8'} - dependencies: - fill-range: 7.1.1 - dev: true - - /brorand@1.1.0: - resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} - dev: true - - /browser-stdout@1.3.1: - resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==} - dev: true - - /browserify-aes@1.2.0: - resolution: {integrity: sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==} - dependencies: - buffer-xor: 1.0.3 - cipher-base: 1.0.6 - create-hash: 1.2.0 - evp_bytestokey: 1.0.3 - inherits: 2.0.4 - safe-buffer: 5.2.1 - dev: true - - /browserslist@4.24.2: - resolution: {integrity: sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - dependencies: - caniuse-lite: 1.0.30001686 - electron-to-chromium: 1.5.70 - node-releases: 2.0.18 - update-browserslist-db: 1.1.1(browserslist@4.24.2) - dev: true - - /bs-logger@0.2.6: - resolution: {integrity: sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==} - engines: {node: '>= 6'} - dependencies: - fast-json-stable-stringify: 2.1.0 - dev: true - - /bs58@4.0.1: - resolution: {integrity: sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==} - dependencies: - base-x: 3.0.10 - dev: true - - /bs58check@2.1.2: - resolution: {integrity: sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==} - dependencies: - bs58: 4.0.1 - create-hash: 1.2.0 - safe-buffer: 5.2.1 - dev: true - - /bser@2.1.1: - resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} - dependencies: - node-int64: 0.4.0 - dev: true - - /buffer-from@1.1.2: - resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} - dev: true - - /buffer-xor@1.0.3: - resolution: {integrity: sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==} - dev: true - - /buffer@4.9.2: - resolution: {integrity: sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==} - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - isarray: 1.0.0 - dev: true - - /buffer@5.7.1: - resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - - /buffer@6.0.3: - resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} - dependencies: - base64-js: 1.5.1 - ieee754: 1.2.1 - dev: true - - /bytes@3.1.2: - resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} - engines: {node: '>= 0.8'} - dev: true - - /cacache@15.3.0: - resolution: {integrity: sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==} - engines: {node: '>= 10'} - requiresBuild: true - dependencies: - '@npmcli/fs': 1.1.1 - '@npmcli/move-file': 1.1.2 - chownr: 2.0.0 - fs-minipass: 2.1.0 - glob: 7.2.3 - infer-owner: 1.0.4 - lru-cache: 6.0.0 - minipass: 3.3.6 - minipass-collect: 1.0.2 - minipass-flush: 1.0.5 - minipass-pipeline: 1.2.4 - mkdirp: 1.0.4 - p-map: 4.0.0 - promise-inflight: 1.0.1 - rimraf: 3.0.2 - ssri: 8.0.1 - tar: 6.2.1 - unique-filename: 1.1.1 - transitivePeerDependencies: - - bluebird - optional: true - - /call-bind@1.0.7: - resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} - engines: {node: '>= 0.4'} - dependencies: - es-define-property: 1.0.0 - es-errors: 1.3.0 - function-bind: 1.1.2 - get-intrinsic: 1.2.4 - set-function-length: 1.2.2 - dev: true - - /callsites@3.1.0: - resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} - engines: {node: '>=6'} - dev: true - - /camelcase@5.3.1: - resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} - engines: {node: '>=6'} - dev: true - - /camelcase@6.3.0: - resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} - engines: {node: '>=10'} - dev: true - - /caniuse-lite@1.0.30001686: - resolution: {integrity: sha512-Y7deg0Aergpa24M3qLC5xjNklnKnhsmSyR/V89dLZ1n0ucJIFNs7PgR2Yfa/Zf6W79SbBicgtGxZr2juHkEUIA==} - dev: true - - /caseless@0.12.0: - resolution: {integrity: sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==} - dev: true - - /cbor@8.1.0: - resolution: {integrity: sha512-DwGjNW9omn6EwP70aXsn7FQJx5kO12tX0bZkaTjzdVFM6/7nhA4t0EENocKGx6D2Bch9PE2KzCUf5SceBdeijg==} - engines: {node: '>=12.19'} - dependencies: - nofilter: 3.1.0 - dev: true - - /cbor@9.0.2: - resolution: {integrity: sha512-JPypkxsB10s9QOWwa6zwPzqE1Md3vqpPc+cai4sAecuCsRyAtAl/pMyhPlMbT/xtPnm2dznJZYRLui57qiRhaQ==} - engines: {node: '>=16'} - dependencies: - nofilter: 3.1.0 - dev: true - - /chai-as-promised@7.1.2(chai@4.5.0): - resolution: {integrity: sha512-aBDHZxRzYnUYuIAIPBH2s511DjlKPzXNlXSGFC8CwmroWQLfrW0LtE1nK3MAwwNhJPa9raEjNCmRoFpG0Hurdw==} - peerDependencies: - chai: '>= 2.1.2 < 6' - dependencies: - chai: 4.5.0 - check-error: 1.0.3 - dev: true - - /chai@4.5.0: - resolution: {integrity: sha512-RITGBfijLkBddZvnn8jdqoTypxvqbOLYQkGGxXzeFjVHvudaPw0HNFD9x928/eUwYWd2dPCugVqspGALTZZQKw==} - engines: {node: '>=4'} - dependencies: - assertion-error: 1.1.0 - check-error: 1.0.3 - deep-eql: 4.1.4 - get-func-name: 2.0.2 - loupe: 2.3.7 - pathval: 1.1.1 - type-detect: 4.1.0 - dev: true - - /chalk@2.4.2: - resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} - engines: {node: '>=4'} - dependencies: - ansi-styles: 3.2.1 - escape-string-regexp: 1.0.5 - supports-color: 5.5.0 - dev: true - - /chalk@4.1.2: - resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - supports-color: 7.2.0 - dev: true - - /char-regex@1.0.2: - resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} - engines: {node: '>=10'} - dev: true - - /charenc@0.0.2: - resolution: {integrity: sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==} - dev: true - - /check-error@1.0.3: - resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} - dependencies: - get-func-name: 2.0.2 - dev: true - - /chokidar@3.6.0: - resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} - engines: {node: '>= 8.10.0'} - dependencies: - anymatch: 3.1.3 - braces: 3.0.3 - glob-parent: 5.1.2 - is-binary-path: 2.1.0 - is-glob: 4.0.3 - normalize-path: 3.0.0 - readdirp: 3.6.0 - optionalDependencies: - fsevents: 2.3.3 - dev: true - - /chokidar@4.0.1: - resolution: {integrity: sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==} - engines: {node: '>= 14.16.0'} - dependencies: - readdirp: 4.0.2 - dev: true - - /chownr@1.1.4: - resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} - - /chownr@2.0.0: - resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} - engines: {node: '>=10'} - - /ci-info@2.0.0: - resolution: {integrity: sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==} - dev: true - - /ci-info@3.9.0: - resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} - engines: {node: '>=8'} - dev: true - - /cipher-base@1.0.6: - resolution: {integrity: sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==} - engines: {node: '>= 0.10'} - dependencies: - inherits: 2.0.4 - safe-buffer: 5.2.1 - dev: true - - /cjs-module-lexer@1.4.1: - resolution: {integrity: sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==} - dev: true - - /clean-stack@2.2.0: - resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} - engines: {node: '>=6'} - - /cli-boxes@2.2.1: - resolution: {integrity: sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==} - engines: {node: '>=6'} - dev: true - - /cli-table3@0.5.1: - resolution: {integrity: sha512-7Qg2Jrep1S/+Q3EceiZtQcDPWxhAvBw+ERf1162v4sikJrvojMHFqXt8QIVha8UlH9rgU0BeWPytZ9/TzYqlUw==} - engines: {node: '>=6'} - dependencies: - object-assign: 4.1.1 - string-width: 2.1.1 - optionalDependencies: - colors: 1.4.0 - dev: true - - /cliui@7.0.4: - resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - dev: true - - /cliui@8.0.1: - resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} - engines: {node: '>=12'} - dependencies: - string-width: 4.2.3 - strip-ansi: 6.0.1 - wrap-ansi: 7.0.0 - dev: true - - /co@4.6.0: - resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} - engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} - dev: true - - /collect-v8-coverage@1.0.2: - resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} - dev: true - - /color-convert@1.9.3: - resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} - dependencies: - color-name: 1.1.3 - dev: true - - /color-convert@2.0.1: - resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} - engines: {node: '>=7.0.0'} - dependencies: - color-name: 1.1.4 - dev: true - - /color-name@1.1.3: - resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} - dev: true - - /color-name@1.1.4: - resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - dev: true - - /color-support@1.1.3: - resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} - hasBin: true - requiresBuild: true - optional: true - - /colors@1.4.0: - resolution: {integrity: sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==} - engines: {node: '>=0.1.90'} - dev: true - - /combined-stream@1.0.8: - resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} - engines: {node: '>= 0.8'} - dependencies: - delayed-stream: 1.0.0 - dev: true - - /command-exists@1.2.9: - resolution: {integrity: sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==} - dev: true - - /command-line-args@5.2.1: - resolution: {integrity: sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==} - engines: {node: '>=4.0.0'} - dependencies: - array-back: 3.1.0 - find-replace: 3.0.0 - lodash.camelcase: 4.3.0 - typical: 4.0.0 - dev: true - - /command-line-usage@6.1.3: - resolution: {integrity: sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw==} - engines: {node: '>=8.0.0'} - dependencies: - array-back: 4.0.2 - chalk: 2.4.2 - table-layout: 1.0.2 - typical: 5.2.0 - dev: true - - /commander@10.0.1: - resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} - engines: {node: '>=14'} - dev: true - - /commander@11.1.0: - resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} - engines: {node: '>=16'} - dev: true - - /commander@8.3.0: - resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} - engines: {node: '>= 12'} - dev: true - - /compare-versions@6.1.1: - resolution: {integrity: sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==} - dev: true - - /concat-map@0.0.1: - resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} - - /concat-stream@1.6.2: - resolution: {integrity: sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==} - engines: {'0': node >= 0.8} - dependencies: - buffer-from: 1.1.2 - inherits: 2.0.4 - readable-stream: 2.3.8 - typedarray: 0.0.6 - dev: true - - /console-control-strings@1.1.0: - resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} - requiresBuild: true - optional: true - - /convert-source-map@2.0.0: - resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} - dev: true - - /cookie@0.4.2: - resolution: {integrity: sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==} - engines: {node: '>= 0.6'} - dev: true - - /core-util-is@1.0.3: - resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} - dev: true - - /cosmiconfig@8.3.6(typescript@5.7.2): - resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==} - engines: {node: '>=14'} - peerDependencies: - typescript: '>=4.9.5' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - import-fresh: 3.3.0 - js-yaml: 4.1.0 - parse-json: 5.2.0 - path-type: 4.0.0 - typescript: 5.7.2 - dev: true - - /create-hash@1.2.0: - resolution: {integrity: sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==} - dependencies: - cipher-base: 1.0.6 - inherits: 2.0.4 - md5.js: 1.3.5 - ripemd160: 2.0.2 - sha.js: 2.4.11 - dev: true - - /create-hmac@1.1.7: - resolution: {integrity: sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==} - dependencies: - cipher-base: 1.0.6 - create-hash: 1.2.0 - inherits: 2.0.4 - ripemd160: 2.0.2 - safe-buffer: 5.2.1 - sha.js: 2.4.11 - dev: true - - /create-jest@29.7.0(@types/node@18.19.67)(ts-node@10.9.2): - resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - hasBin: true - dependencies: - '@jest/types': 29.6.3 - chalk: 4.1.2 - exit: 0.1.2 - graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@18.19.67)(ts-node@10.9.2) - jest-util: 29.7.0 - prompts: 2.4.2 - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - dev: true - - /create-require@1.1.1: - resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} - dev: true - - /cross-env@7.0.3: - resolution: {integrity: sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==} - engines: {node: '>=10.14', npm: '>=6', yarn: '>=1'} - hasBin: true - dependencies: - cross-spawn: 7.0.6 - dev: true - - /cross-spawn@7.0.6: - resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} - engines: {node: '>= 8'} - dependencies: - path-key: 3.1.1 - shebang-command: 2.0.0 - which: 2.0.2 - dev: true - - /crypt@0.0.2: - resolution: {integrity: sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==} - dev: true - - /death@1.1.0: - resolution: {integrity: sha512-vsV6S4KVHvTGxbEcij7hkWRv0It+sGGWVOM67dQde/o5Xjnr+KmLjxWJii2uEObIrt1CcM9w0Yaovx+iOlIL+w==} - dev: true - - /debug@4.3.7(supports-color@8.1.1): - resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - dependencies: - ms: 2.1.3 - supports-color: 8.1.1 - - /decamelize@4.0.0: - resolution: {integrity: sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==} - engines: {node: '>=10'} - dev: true - - /decompress-response@6.0.0: - resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} - engines: {node: '>=10'} - dependencies: - mimic-response: 3.1.0 - - /dedent@1.5.3: - resolution: {integrity: sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==} - peerDependencies: - babel-plugin-macros: ^3.1.0 - peerDependenciesMeta: - babel-plugin-macros: - optional: true - dev: true - - /deep-eql@4.1.4: - resolution: {integrity: sha512-SUwdGfqdKOwxCPeVYjwSyRpJ7Z+fhpwIAtmCUdZIWZ/YP5R9WAsyuSgpLVDi9bjWoN2LXHNss/dk3urXtdQxGg==} - engines: {node: '>=6'} - dependencies: - type-detect: 4.1.0 - dev: true - - /deep-extend@0.6.0: - resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} - engines: {node: '>=4.0.0'} - - /deep-is@0.1.4: - resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} - dev: true - - /deepmerge@4.3.1: - resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} - engines: {node: '>=0.10.0'} - dev: true - - /define-data-property@1.1.4: - resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} - engines: {node: '>= 0.4'} - dependencies: - es-define-property: 1.0.0 - es-errors: 1.3.0 - gopd: 1.1.0 - dev: true - - /delayed-stream@1.0.0: - resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} - engines: {node: '>=0.4.0'} - dev: true - - /delegates@1.0.0: - resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} - requiresBuild: true - optional: true - - /depd@2.0.0: - resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} - engines: {node: '>= 0.8'} - dev: true - - /dequal@2.0.3: - resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} - engines: {node: '>=6'} - dev: true - - /detect-libc@2.0.3: - resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} - engines: {node: '>=8'} - - /detect-newline@3.1.0: - resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} - engines: {node: '>=8'} - dev: true - - /diff-sequences@29.6.3: - resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dev: true - - /diff@4.0.2: - resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} - engines: {node: '>=0.3.1'} - dev: true - - /diff@5.2.0: - resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} - engines: {node: '>=0.3.1'} - dev: true - - /difflib@0.2.4: - resolution: {integrity: sha512-9YVwmMb0wQHQNr5J9m6BSj6fk4pfGITGQOOs+D9Fl+INODWFOfvhIU1hNv6GgR1RBoC/9NJcwu77zShxV0kT7w==} - dependencies: - heap: 0.2.7 - dev: true - - /dir-glob@3.0.1: - resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} - engines: {node: '>=8'} - dependencies: - path-type: 4.0.0 - dev: true - - /dotenv@16.4.6: - resolution: {integrity: sha512-JhcR/+KIjkkjiU8yEpaB/USlzVi3i5whwOjpIRNGi9svKEXZSe+Qp6IWAjFjv+2GViAoDRCUv/QLNziQxsLqDg==} - engines: {node: '>=12'} - dev: true - - /ejs@3.1.10: - resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} - engines: {node: '>=0.10.0'} - hasBin: true - dependencies: - jake: 10.9.2 - dev: true - - /electron-to-chromium@1.5.70: - resolution: {integrity: sha512-P6FPqAWIZrC3sHDAwBitJBs7N7IF58m39XVny7DFseQXK2eiMn7nNQizFf63mWDDUnFvaqsM8FI0+ZZfLkdUGA==} - dev: true - - /elliptic@6.5.4: - resolution: {integrity: sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==} - dependencies: - bn.js: 4.12.1 - brorand: 1.1.0 - hash.js: 1.1.7 - hmac-drbg: 1.0.1 - inherits: 2.0.4 - minimalistic-assert: 1.0.1 - minimalistic-crypto-utils: 1.0.1 - dev: true - - /elliptic@6.6.1: - resolution: {integrity: sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==} - dependencies: - bn.js: 4.12.1 - brorand: 1.1.0 - hash.js: 1.1.7 - hmac-drbg: 1.0.1 - inherits: 2.0.4 - minimalistic-assert: 1.0.1 - minimalistic-crypto-utils: 1.0.1 - dev: true - - /emittery@0.13.1: - resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} - engines: {node: '>=12'} - dev: true - - /emoji-regex@8.0.0: - resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} - - /encode-utf8@1.0.3: - resolution: {integrity: sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==} - dev: true - - /encoding@0.1.13: - resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} - requiresBuild: true - dependencies: - iconv-lite: 0.6.3 - optional: true - - /end-of-stream@1.4.4: - resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} - dependencies: - once: 1.4.0 - - /enquirer@2.4.1: - resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} - engines: {node: '>=8.6'} - dependencies: - ansi-colors: 4.1.3 - strip-ansi: 6.0.1 - dev: true - - /env-paths@2.2.1: - resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} - engines: {node: '>=6'} - - /err-code@2.0.3: - resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==} - requiresBuild: true - optional: true - - /error-ex@1.3.2: - resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} - dependencies: - is-arrayish: 0.2.1 - dev: true - - /es-define-property@1.0.0: - resolution: {integrity: sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==} - engines: {node: '>= 0.4'} - dependencies: - get-intrinsic: 1.2.4 - dev: true - - /es-errors@1.3.0: - resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} - engines: {node: '>= 0.4'} - dev: true - - /escalade@3.2.0: - resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} - engines: {node: '>=6'} - dev: true - - /escape-string-regexp@1.0.5: - resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} - engines: {node: '>=0.8.0'} - dev: true - - /escape-string-regexp@2.0.0: - resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} - engines: {node: '>=8'} - dev: true - - /escape-string-regexp@4.0.0: - resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} - engines: {node: '>=10'} - dev: true - - /escodegen@1.8.1: - resolution: {integrity: sha512-yhi5S+mNTOuRvyW4gWlg5W1byMaQGWWSYHXsuFZ7GBo7tpyOwi2EdzMP/QWxh9hwkD2m+wDVHJsxhRIj+v/b/A==} - engines: {node: '>=0.12.0'} - hasBin: true - dependencies: - esprima: 2.7.3 - estraverse: 1.9.3 - esutils: 2.0.3 - optionator: 0.8.3 - optionalDependencies: - source-map: 0.2.0 - dev: true - - /eslint-config-prettier@8.10.0(eslint@9.16.0): - resolution: {integrity: sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==} - hasBin: true - peerDependencies: - eslint: '>=7.0.0' - dependencies: - eslint: 9.16.0 - dev: true - - /eslint-scope@8.2.0: - resolution: {integrity: sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - dependencies: - esrecurse: 4.3.0 - estraverse: 5.3.0 - dev: true - - /eslint-visitor-keys@3.4.3: - resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - dev: true - - /eslint-visitor-keys@4.2.0: - resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - dev: true - - /eslint@9.16.0: - resolution: {integrity: sha512-whp8mSQI4C8VXd+fLgSM0lh3UlmcFtVwUQjyKCFfsp+2ItAIYhlq/hqGahGqHE6cv9unM41VlqKk2VtKYR2TaA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - hasBin: true - peerDependencies: - jiti: '*' - peerDependenciesMeta: - jiti: - optional: true - dependencies: - '@eslint-community/eslint-utils': 4.4.1(eslint@9.16.0) - '@eslint-community/regexpp': 4.12.1 - '@eslint/config-array': 0.19.0 - '@eslint/core': 0.9.0 - '@eslint/eslintrc': 3.2.0 - '@eslint/js': 9.16.0 - '@eslint/plugin-kit': 0.2.3 - '@humanfs/node': 0.16.6 - '@humanwhocodes/module-importer': 1.0.1 - '@humanwhocodes/retry': 0.4.1 - '@types/estree': 1.0.6 - '@types/json-schema': 7.0.15 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.6 - debug: 4.3.7(supports-color@8.1.1) - escape-string-regexp: 4.0.0 - eslint-scope: 8.2.0 - eslint-visitor-keys: 4.2.0 - espree: 10.3.0 - esquery: 1.6.0 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 8.0.0 - find-up: 5.0.0 - glob-parent: 6.0.2 - ignore: 5.3.2 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - json-stable-stringify-without-jsonify: 1.0.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.4 - transitivePeerDependencies: - - supports-color - dev: true - - /espree@10.3.0: - resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - dependencies: - acorn: 8.14.0 - acorn-jsx: 5.3.2(acorn@8.14.0) - eslint-visitor-keys: 4.2.0 - dev: true - - /esprima@2.7.3: - resolution: {integrity: sha512-OarPfz0lFCiW4/AV2Oy1Rp9qu0iusTKqykwTspGCZtPxmF81JR4MmIebvF1F9+UOKth2ZubLQ4XGGaU+hSn99A==} - engines: {node: '>=0.10.0'} - hasBin: true - dev: true - - /esprima@4.0.1: - resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} - engines: {node: '>=4'} - hasBin: true - dev: true - - /esquery@1.6.0: - resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} - engines: {node: '>=0.10'} - dependencies: - estraverse: 5.3.0 - dev: true - - /esrecurse@4.3.0: - resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} - engines: {node: '>=4.0'} - dependencies: - estraverse: 5.3.0 - dev: true - - /estraverse@1.9.3: - resolution: {integrity: sha512-25w1fMXQrGdoquWnScXZGckOv+Wes+JDnuN/+7ex3SauFRS72r2lFDec0EKPt2YD1wUJ/IrfEex+9yp4hfSOJA==} - engines: {node: '>=0.10.0'} - dev: true - - /estraverse@5.3.0: - resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} - engines: {node: '>=4.0'} - dev: true - - /esutils@2.0.3: - resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} - engines: {node: '>=0.10.0'} - dev: true - - /eth-gas-reporter@0.2.27: - resolution: {integrity: sha512-femhvoAM7wL0GcI8ozTdxfuBtBFJ9qsyIAsmKVjlWAHUbdnnXHt+lKzz/kmldM5lA9jLuNHGwuIxorNpLbR1Zw==} - peerDependencies: - '@codechecks/client': ^0.1.0 - peerDependenciesMeta: - '@codechecks/client': - optional: true - dependencies: - '@solidity-parser/parser': 0.14.5 - axios: 1.7.8(debug@4.3.7) - cli-table3: 0.5.1 - colors: 1.4.0 - ethereum-cryptography: 1.2.0 - ethers: 5.7.2 - fs-readdir-recursive: 1.1.0 - lodash: 4.17.21 - markdown-table: 1.1.3 - mocha: 10.8.2 - req-cwd: 2.0.0 - sha1: 1.1.1 - sync-request: 6.1.0 - transitivePeerDependencies: - - bufferutil - - debug - - utf-8-validate - dev: true - - /ethereum-bloom-filters@1.2.0: - resolution: {integrity: sha512-28hyiE7HVsWubqhpVLVmZXFd4ITeHi+BUu05o9isf0GUpMtzBUi+8/gFrGaGYzvGAJQmJ3JKj77Mk9G98T84rA==} - dependencies: - '@noble/hashes': 1.6.1 - dev: true - - /ethereum-cryptography@0.1.3: - resolution: {integrity: sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==} - dependencies: - '@types/pbkdf2': 3.1.2 - '@types/secp256k1': 4.0.6 - blakejs: 1.2.1 - browserify-aes: 1.2.0 - bs58check: 2.1.2 - create-hash: 1.2.0 - create-hmac: 1.1.7 - hash.js: 1.1.7 - keccak: 3.0.4 - pbkdf2: 3.1.2 - randombytes: 2.1.0 - safe-buffer: 5.2.1 - scrypt-js: 3.0.1 - secp256k1: 4.0.4 - setimmediate: 1.0.5 - dev: true - - /ethereum-cryptography@1.2.0: - resolution: {integrity: sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw==} - dependencies: - '@noble/hashes': 1.2.0 - '@noble/secp256k1': 1.7.1 - '@scure/bip32': 1.1.5 - '@scure/bip39': 1.1.1 - dev: true - - /ethereum-cryptography@2.2.1: - resolution: {integrity: sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==} - dependencies: - '@noble/curves': 1.4.2 - '@noble/hashes': 1.4.0 - '@scure/bip32': 1.4.0 - '@scure/bip39': 1.3.0 - dev: true - - /ethereumjs-abi@0.6.8: - resolution: {integrity: sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA==} - deprecated: This library has been deprecated and usage is discouraged. - dependencies: - bn.js: 4.12.1 - ethereumjs-util: 6.2.1 - dev: true - - /ethereumjs-util@6.2.1: - resolution: {integrity: sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==} - dependencies: - '@types/bn.js': 4.11.6 - bn.js: 4.12.1 - create-hash: 1.2.0 - elliptic: 6.6.1 - ethereum-cryptography: 0.1.3 - ethjs-util: 0.1.6 - rlp: 2.2.7 - dev: true - - /ethereumjs-util@7.1.5: - resolution: {integrity: sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg==} - engines: {node: '>=10.0.0'} - dependencies: - '@types/bn.js': 5.1.6 - bn.js: 5.2.1 - create-hash: 1.2.0 - ethereum-cryptography: 0.1.3 - rlp: 2.2.7 - dev: true - - /ethers@5.7.2: - resolution: {integrity: sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg==} - dependencies: - '@ethersproject/abi': 5.7.0 - '@ethersproject/abstract-provider': 5.7.0 - '@ethersproject/abstract-signer': 5.7.0 - '@ethersproject/address': 5.7.0 - '@ethersproject/base64': 5.7.0 - '@ethersproject/basex': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/constants': 5.7.0 - '@ethersproject/contracts': 5.7.0 - '@ethersproject/hash': 5.7.0 - '@ethersproject/hdnode': 5.7.0 - '@ethersproject/json-wallets': 5.7.0 - '@ethersproject/keccak256': 5.7.0 - '@ethersproject/logger': 5.7.0 - '@ethersproject/networks': 5.7.1 - '@ethersproject/pbkdf2': 5.7.0 - '@ethersproject/properties': 5.7.0 - '@ethersproject/providers': 5.7.2 - '@ethersproject/random': 5.7.0 - '@ethersproject/rlp': 5.7.0 - '@ethersproject/sha2': 5.7.0 - '@ethersproject/signing-key': 5.7.0 - '@ethersproject/solidity': 5.7.0 - '@ethersproject/strings': 5.7.0 - '@ethersproject/transactions': 5.7.0 - '@ethersproject/units': 5.7.0 - '@ethersproject/wallet': 5.7.0 - '@ethersproject/web': 5.7.1 - '@ethersproject/wordlists': 5.7.0 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - dev: true - - /ethers@6.13.4: - resolution: {integrity: sha512-21YtnZVg4/zKkCQPjrDj38B1r4nQvTZLopUGMLQ1ePU2zV/joCfDC3t3iKQjWRzjjjbzR+mdAIoikeBRNkdllA==} - engines: {node: '>=14.0.0'} - dependencies: - '@adraffy/ens-normalize': 1.10.1 - '@noble/curves': 1.2.0 - '@noble/hashes': 1.3.2 - '@types/node': 22.7.5 - aes-js: 4.0.0-beta.5 - tslib: 2.7.0 - ws: 8.17.1 - transitivePeerDependencies: - - bufferutil - - utf-8-validate - dev: true - - /ethjs-unit@0.1.6: - resolution: {integrity: sha512-/Sn9Y0oKl0uqQuvgFk/zQgR7aw1g36qX/jzSQ5lSwlO0GigPymk4eGQfeNTD03w1dPOqfz8V77Cy43jH56pagw==} - engines: {node: '>=6.5.0', npm: '>=3'} - dependencies: - bn.js: 4.11.6 - number-to-bn: 1.7.0 - dev: true - - /ethjs-util@0.1.6: - resolution: {integrity: sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==} - engines: {node: '>=6.5.0', npm: '>=3'} - dependencies: - is-hex-prefixed: 1.0.0 - strip-hex-prefix: 1.0.0 - dev: true - - /evp_bytestokey@1.0.3: - resolution: {integrity: sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==} - dependencies: - md5.js: 1.3.5 - safe-buffer: 5.2.1 - dev: true - - /execa@5.1.1: - resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} - engines: {node: '>=10'} - dependencies: - cross-spawn: 7.0.6 - get-stream: 6.0.1 - human-signals: 2.1.0 - is-stream: 2.0.1 - merge-stream: 2.0.0 - npm-run-path: 4.0.1 - onetime: 5.1.2 - signal-exit: 3.0.7 - strip-final-newline: 2.0.0 - dev: true - - /exit@0.1.2: - resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} - engines: {node: '>= 0.8.0'} - dev: true - - /expand-template@2.0.3: - resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} - engines: {node: '>=6'} - - /expect@29.7.0: - resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/expect-utils': 29.7.0 - jest-get-type: 29.6.3 - jest-matcher-utils: 29.7.0 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - dev: true - - /extra-bigint@1.2.0: - resolution: {integrity: sha512-F9T/pcT5xPZTjlFMKGCZgBY2/jKqEPxXHT4kLSwsa7gp7D05nQq8z9NzRTzVy5Z4AOO1E/iD9r9OBz4csGD7nw==} - - /fast-base64-decode@1.0.0: - resolution: {integrity: sha512-qwaScUgUGBYeDNRnbc/KyllVU88Jk1pRHPStuF/lO7B0/RTRLj7U0lkdTAutlBblY08rwZDff6tNU9cjv6j//Q==} - dev: true - - /fast-deep-equal@3.1.3: - resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} - dev: true - - /fast-diff@1.3.0: - resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} - dev: true - - /fast-glob@3.3.2: - resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} - engines: {node: '>=8.6.0'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.8 - dev: true - - /fast-json-stable-stringify@2.1.0: - resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} - dev: true - - /fast-levenshtein@2.0.6: - resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} - dev: true - - /fast-uri@3.0.3: - resolution: {integrity: sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==} - dev: true - - /fastq@1.17.1: - resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} - dependencies: - reusify: 1.0.4 - dev: true - - /fb-watchman@2.0.2: - resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} - dependencies: - bser: 2.1.1 - dev: true - - /fdir@6.4.2(picomatch@4.0.2): - resolution: {integrity: sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ==} - peerDependencies: - picomatch: ^3 || ^4 - peerDependenciesMeta: - picomatch: - optional: true - dependencies: - picomatch: 4.0.2 - dev: true - - /fetch-mock@11.1.5: - resolution: {integrity: sha512-KHmZDnZ1ry0pCTrX4YG5DtThHi0MH+GNI9caESnzX/nMJBrvppUHMvLx47M0WY9oAtKOMiPfZDRpxhlHg89BOA==} - engines: {node: '>=8.0.0'} - peerDependencies: - node-fetch: '*' - peerDependenciesMeta: - node-fetch: - optional: true - dependencies: - '@types/glob-to-regexp': 0.4.4 - dequal: 2.0.3 - glob-to-regexp: 0.4.1 - is-subset: 0.1.1 - regexparam: 3.0.0 - dev: true - - /fhevm-contracts@0.2.0: - resolution: {integrity: sha512-uzNDsz1BFMACk3OG1bHnsPpB0+tof9ld8kbuqEZAGqE0ughlaHJxvFOT1UUNXjDtcML9prJJTCSiX2hXDMhm0w==} - dependencies: - '@openzeppelin/contracts': 5.0.2 - '@openzeppelin/contracts-upgradeable': 5.0.2(@openzeppelin/contracts@5.0.2) - extra-bigint: 1.2.0 - sqlite3: 5.1.7 - transitivePeerDependencies: - - bluebird - - supports-color - dev: false - - /fhevm-core-contracts@0.6.0-5: - resolution: {integrity: sha512-o3ZInT2RA+uldzIMM2fHMjoIhI2466psLGI4tU4BJYOeV6wgJpw+T+m6/tN3WSf3nE0bU4yLrD1S/lM3Wk24vg==} - dev: true - - /fhevm@0.6.0: - resolution: {integrity: sha512-6tcVRLzlhg0s1gThACYCVP94Ir/k61Zaj4IsVyEBFP7WJEHdeOF61OYUZIIKlMofKdToVBadNus+XO8ys47Ysw==} - engines: {node: '>=20.0.0'} - dependencies: - '@openzeppelin/contracts': 5.1.0 - extra-bigint: 1.2.0 - sqlite3: 5.1.7 - transitivePeerDependencies: - - bluebird - - supports-color - dev: true - - /fhevmjs@0.6.0: - resolution: {integrity: sha512-xukyiXv+KertTTEIhFuZp2jW31RBOXUC6TfVZBAUVEr1xiTnvXtePwuutvqj3rabnclRBTzr/j4UmEPvCaGXQw==} - engines: {node: '>=20'} - hasBin: true - dependencies: - bigint-buffer: 1.1.5 - commander: 11.1.0 - fetch-mock: 11.1.5 - keccak: 3.0.4 - node-tfhe: 0.9.1 - node-tkms: 0.9.0-rc36 - tfhe: 0.9.1 - tkms: 0.9.0-rc36 - wasm-feature-detect: 1.8.0 - transitivePeerDependencies: - - node-fetch - dev: true - - /file-entry-cache@8.0.0: - resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} - engines: {node: '>=16.0.0'} - dependencies: - flat-cache: 4.0.1 - dev: true - - /file-uri-to-path@1.0.0: - resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} - - /filelist@1.0.4: - resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} - dependencies: - minimatch: 5.1.6 - dev: true - - /fill-range@7.1.1: - resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} - engines: {node: '>=8'} - dependencies: - to-regex-range: 5.0.1 - dev: true - - /find-replace@3.0.0: - resolution: {integrity: sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==} - engines: {node: '>=4.0.0'} - dependencies: - array-back: 3.1.0 - dev: true - - /find-up@4.1.0: - resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} - engines: {node: '>=8'} - dependencies: - locate-path: 5.0.0 - path-exists: 4.0.0 - dev: true - - /find-up@5.0.0: - resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} - engines: {node: '>=10'} - dependencies: - locate-path: 6.0.0 - path-exists: 4.0.0 - dev: true - - /flat-cache@4.0.1: - resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} - engines: {node: '>=16'} - dependencies: - flatted: 3.3.2 - keyv: 4.5.4 - dev: true - - /flat@5.0.2: - resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} - hasBin: true - dev: true - - /flatted@3.3.2: - resolution: {integrity: sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==} - dev: true - - /fmix@0.1.0: - resolution: {integrity: sha512-Y6hyofImk9JdzU8k5INtTXX1cu8LDlePWDFU5sftm9H+zKCr5SGrVjdhkvsim646cw5zD0nADj8oHyXMZmCZ9w==} - dependencies: - imul: 1.0.1 - dev: true - - /follow-redirects@1.15.9(debug@4.3.7): - resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} - engines: {node: '>=4.0'} - peerDependencies: - debug: '*' - peerDependenciesMeta: - debug: - optional: true - dependencies: - debug: 4.3.7(supports-color@8.1.1) - dev: true - - /for-each@0.3.3: - resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} - dependencies: - is-callable: 1.2.7 - dev: true - - /form-data@2.5.2: - resolution: {integrity: sha512-GgwY0PS7DbXqajuGf4OYlsrIu3zgxD6Vvql43IBhm6MahqA5SK/7mwhtNj2AdH2z35YR34ujJ7BN+3fFC3jP5Q==} - engines: {node: '>= 0.12'} - dependencies: - asynckit: 0.4.0 - combined-stream: 1.0.8 - mime-types: 2.1.35 - safe-buffer: 5.2.1 - dev: true - - /form-data@4.0.1: - resolution: {integrity: sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==} - engines: {node: '>= 6'} - dependencies: - asynckit: 0.4.0 - combined-stream: 1.0.8 - mime-types: 2.1.35 - dev: true - - /fp-ts@1.19.3: - resolution: {integrity: sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg==} - dev: true - - /fs-constants@1.0.0: - resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} - - /fs-extra@10.1.0: - resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} - engines: {node: '>=12'} - dependencies: - graceful-fs: 4.2.11 - jsonfile: 6.1.0 - universalify: 2.0.1 - dev: true - - /fs-extra@7.0.1: - resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} - engines: {node: '>=6 <7 || >=8'} - dependencies: - graceful-fs: 4.2.11 - jsonfile: 4.0.0 - universalify: 0.1.2 - dev: true - - /fs-extra@8.1.0: - resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} - engines: {node: '>=6 <7 || >=8'} - dependencies: - graceful-fs: 4.2.11 - jsonfile: 4.0.0 - universalify: 0.1.2 - dev: true - - /fs-extra@9.1.0: - resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} - engines: {node: '>=10'} - dependencies: - at-least-node: 1.0.0 - graceful-fs: 4.2.11 - jsonfile: 6.1.0 - universalify: 2.0.1 - dev: true - - /fs-minipass@2.1.0: - resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==} - engines: {node: '>= 8'} - dependencies: - minipass: 3.3.6 - - /fs-readdir-recursive@1.1.0: - resolution: {integrity: sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==} - dev: true - - /fs.realpath@1.0.0: - resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} - - /fsevents@2.3.3: - resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} - engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /function-bind@1.1.2: - resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - dev: true - - /gauge@4.0.4: - resolution: {integrity: sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - deprecated: This package is no longer supported. - requiresBuild: true - dependencies: - aproba: 2.0.0 - color-support: 1.1.3 - console-control-strings: 1.1.0 - has-unicode: 2.0.1 - signal-exit: 3.0.7 - string-width: 4.2.3 - strip-ansi: 6.0.1 - wide-align: 1.1.5 - optional: true - - /gensync@1.0.0-beta.2: - resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} - engines: {node: '>=6.9.0'} - dev: true - - /get-caller-file@2.0.5: - resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} - engines: {node: 6.* || 8.* || >= 10.*} - dev: true - - /get-func-name@2.0.2: - resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} - dev: true - - /get-intrinsic@1.2.4: - resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} - engines: {node: '>= 0.4'} - dependencies: - es-errors: 1.3.0 - function-bind: 1.1.2 - has-proto: 1.1.0 - has-symbols: 1.1.0 - hasown: 2.0.2 - dev: true - - /get-package-type@0.1.0: - resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} - engines: {node: '>=8.0.0'} - dev: true - - /get-port@3.2.0: - resolution: {integrity: sha512-x5UJKlgeUiNT8nyo/AcnwLnZuZNcSjSw0kogRB+Whd1fjjFq4B1hySFxSFWWSn4mIBzg3sRNUDFYc4g5gjPoLg==} - engines: {node: '>=4'} - dev: true - - /get-stream@6.0.1: - resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} - engines: {node: '>=10'} - dev: true - - /ghost-testrpc@0.0.2: - resolution: {integrity: sha512-i08dAEgJ2g8z5buJIrCTduwPIhih3DP+hOCTyyryikfV8T0bNvHnGXO67i0DD1H4GBDETTclPy9njZbfluQYrQ==} - hasBin: true - dependencies: - chalk: 2.4.2 - node-emoji: 1.11.0 - dev: true - - /github-from-package@0.0.0: - resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} - - /glob-parent@5.1.2: - resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} - engines: {node: '>= 6'} - dependencies: - is-glob: 4.0.3 - dev: true - - /glob-parent@6.0.2: - resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} - engines: {node: '>=10.13.0'} - dependencies: - is-glob: 4.0.3 - dev: true - - /glob-to-regexp@0.4.1: - resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} - dev: true - - /glob@5.0.15: - resolution: {integrity: sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA==} - deprecated: Glob versions prior to v9 are no longer supported - dependencies: - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - dev: true - - /glob@7.1.7: - resolution: {integrity: sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==} - deprecated: Glob versions prior to v9 are no longer supported - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - dev: true - - /glob@7.2.3: - resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - deprecated: Glob versions prior to v9 are no longer supported - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 3.1.2 - once: 1.4.0 - path-is-absolute: 1.0.1 - - /glob@8.1.0: - resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} - engines: {node: '>=12'} - deprecated: Glob versions prior to v9 are no longer supported - dependencies: - fs.realpath: 1.0.0 - inflight: 1.0.6 - inherits: 2.0.4 - minimatch: 5.1.6 - once: 1.4.0 - dev: true - - /glob@9.3.5: - resolution: {integrity: sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==} - engines: {node: '>=16 || 14 >=14.17'} - dependencies: - fs.realpath: 1.0.0 - minimatch: 8.0.4 - minipass: 4.2.8 - path-scurry: 1.11.1 - dev: true - - /global-modules@2.0.0: - resolution: {integrity: sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==} - engines: {node: '>=6'} - dependencies: - global-prefix: 3.0.0 - dev: true - - /global-prefix@3.0.0: - resolution: {integrity: sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==} - engines: {node: '>=6'} - dependencies: - ini: 1.3.8 - kind-of: 6.0.3 - which: 1.3.1 - dev: true - - /globals@11.12.0: - resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} - engines: {node: '>=4'} - dev: true - - /globals@14.0.0: - resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} - engines: {node: '>=18'} - dev: true - - /globals@15.13.0: - resolution: {integrity: sha512-49TewVEz0UxZjr1WYYsWpPrhyC/B/pA8Bq0fUmet2n+eR7yn0IvNzNaoBwnK6mdkzcN+se7Ez9zUgULTz2QH4g==} - engines: {node: '>=18'} - dev: true - - /globby@10.0.2: - resolution: {integrity: sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==} - engines: {node: '>=8'} - dependencies: - '@types/glob': 7.2.0 - array-union: 2.1.0 - dir-glob: 3.0.1 - fast-glob: 3.3.2 - glob: 7.2.3 - ignore: 5.3.2 - merge2: 1.4.1 - slash: 3.0.0 - dev: true - - /gopd@1.1.0: - resolution: {integrity: sha512-FQoVQnqcdk4hVM4JN1eromaun4iuS34oStkdlLENLdpULsuQcTyXj8w7ayhuUfPwEYZ1ZOooOTT6fdA9Vmx/RA==} - engines: {node: '>= 0.4'} - dependencies: - get-intrinsic: 1.2.4 - dev: true - - /graceful-fs@4.2.11: - resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} - - /graphemer@1.4.0: - resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} - dev: true - - /handlebars@4.7.8: - resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==} - engines: {node: '>=0.4.7'} - hasBin: true - dependencies: - minimist: 1.2.8 - neo-async: 2.6.2 - source-map: 0.6.1 - wordwrap: 1.0.0 - optionalDependencies: - uglify-js: 3.19.3 - dev: true - - /hardhat-deploy@0.12.4: - resolution: {integrity: sha512-bYO8DIyeGxZWlhnMoCBon9HNZb6ji0jQn7ngP1t5UmGhC8rQYhji7B73qETMOFhzt5ECZPr+U52duj3nubsqdQ==} - dependencies: - '@ethersproject/abi': 5.7.0 - '@ethersproject/abstract-signer': 5.7.0 - '@ethersproject/address': 5.7.0 - '@ethersproject/bignumber': 5.7.0 - '@ethersproject/bytes': 5.7.0 - '@ethersproject/constants': 5.7.0 - '@ethersproject/contracts': 5.7.0 - '@ethersproject/providers': 5.7.2 - '@ethersproject/solidity': 5.7.0 - '@ethersproject/transactions': 5.7.0 - '@ethersproject/wallet': 5.7.0 - '@types/qs': 6.9.17 - axios: 0.21.4(debug@4.3.7) - chalk: 4.1.2 - chokidar: 3.6.0 - debug: 4.3.7(supports-color@8.1.1) - enquirer: 2.4.1 - ethers: 5.7.2 - form-data: 4.0.1 - fs-extra: 10.1.0 - match-all: 1.2.6 - murmur-128: 0.2.1 - qs: 6.13.1 - zksync-ethers: 5.10.0(ethers@5.7.2) - transitivePeerDependencies: - - bufferutil - - supports-color - - utf-8-validate - dev: true - - /hardhat-gas-reporter@1.0.10(hardhat@2.22.17): - resolution: {integrity: sha512-02N4+So/fZrzJ88ci54GqwVA3Zrf0C9duuTyGt0CFRIh/CdNwbnTgkXkRfojOMLBQ+6t+lBIkgbsOtqMvNwikA==} - peerDependencies: - hardhat: ^2.0.2 - dependencies: - array-uniq: 1.0.3 - eth-gas-reporter: 0.2.27 - hardhat: 2.22.17(ts-node@10.9.2)(typescript@5.7.2) - sha1: 1.1.1 - transitivePeerDependencies: - - '@codechecks/client' - - bufferutil - - debug - - utf-8-validate - dev: true - - /hardhat-ignore-warnings@0.2.12: - resolution: {integrity: sha512-SaxCLKzYBMk3Rd1275TnanUmmxwgU+bu4Ekf2MKcqXxxt6xTGcPTtTaM+USrLgmejZHC4Itg/PaWITlOp4RL3g==} - dependencies: - minimatch: 5.1.6 - node-interval-tree: 2.1.2 - solidity-comments: 0.0.2 - dev: true - - /hardhat-preprocessor@0.1.5(hardhat@2.22.17): - resolution: {integrity: sha512-j8m44mmPxpxAAd0G8fPHRHOas/INZdzptSur0TNJvMEGcFdLDhbHHxBcqZVQ/bmiW42q4gC60AP4CXn9EF018g==} - peerDependencies: - hardhat: ^2.0.5 - dependencies: - hardhat: 2.22.17(ts-node@10.9.2)(typescript@5.7.2) - murmur-128: 0.2.1 - dev: true - - /hardhat@2.22.17(ts-node@10.9.2)(typescript@5.7.2): - resolution: {integrity: sha512-tDlI475ccz4d/dajnADUTRc1OJ3H8fpP9sWhXhBPpYsQOg8JHq5xrDimo53UhWPl7KJmAeDCm1bFG74xvpGRpg==} - hasBin: true - peerDependencies: - ts-node: '*' - typescript: '*' - peerDependenciesMeta: - ts-node: - optional: true - typescript: - optional: true - dependencies: - '@ethersproject/abi': 5.7.0 - '@metamask/eth-sig-util': 4.0.1 - '@nomicfoundation/edr': 0.6.5 - '@nomicfoundation/ethereumjs-common': 4.0.4 - '@nomicfoundation/ethereumjs-tx': 5.0.4 - '@nomicfoundation/ethereumjs-util': 9.0.4 - '@nomicfoundation/solidity-analyzer': 0.1.2 - '@sentry/node': 5.30.0 - '@types/bn.js': 5.1.6 - '@types/lru-cache': 5.1.1 - adm-zip: 0.4.16 - aggregate-error: 3.1.0 - ansi-escapes: 4.3.2 - boxen: 5.1.2 - chokidar: 4.0.1 - ci-info: 2.0.0 - debug: 4.3.7(supports-color@8.1.1) - enquirer: 2.4.1 - env-paths: 2.2.1 - ethereum-cryptography: 1.2.0 - ethereumjs-abi: 0.6.8 - find-up: 5.0.0 - fp-ts: 1.19.3 - fs-extra: 7.0.1 - immutable: 4.3.7 - io-ts: 1.10.4 - json-stream-stringify: 3.1.6 - keccak: 3.0.4 - lodash: 4.17.21 - mnemonist: 0.38.5 - mocha: 10.8.2 - p-map: 4.0.0 - picocolors: 1.1.1 - raw-body: 2.5.2 - resolve: 1.17.0 - semver: 6.3.1 - solc: 0.8.26(debug@4.3.7) - source-map-support: 0.5.21 - stacktrace-parser: 0.1.10 - tinyglobby: 0.2.10 - ts-node: 10.9.2(@types/node@18.19.67)(typescript@5.7.2) - tsort: 0.0.1 - typescript: 5.7.2 - undici: 5.28.4 - uuid: 8.3.2 - ws: 7.5.10 - transitivePeerDependencies: - - bufferutil - - c-kzg - - supports-color - - utf-8-validate - dev: true - - /has-flag@1.0.0: - resolution: {integrity: sha512-DyYHfIYwAJmjAjSSPKANxI8bFY9YtFrgkAfinBojQ8YJTOuOuav64tMUJv584SES4xl74PmuaevIyaLESHdTAA==} - engines: {node: '>=0.10.0'} - dev: true - - /has-flag@3.0.0: - resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} - engines: {node: '>=4'} - dev: true - - /has-flag@4.0.0: - resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} - engines: {node: '>=8'} - - /has-property-descriptors@1.0.2: - resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} - dependencies: - es-define-property: 1.0.0 - dev: true - - /has-proto@1.1.0: - resolution: {integrity: sha512-QLdzI9IIO1Jg7f9GT1gXpPpXArAn6cS31R1eEZqz08Gc+uQ8/XiqHWt17Fiw+2p6oTTIq5GXEpQkAlA88YRl/Q==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - dev: true - - /has-symbols@1.1.0: - resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} - engines: {node: '>= 0.4'} - dev: true - - /has-tostringtag@1.0.2: - resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} - engines: {node: '>= 0.4'} - dependencies: - has-symbols: 1.1.0 - dev: true - - /has-unicode@2.0.1: - resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} - requiresBuild: true - optional: true - - /hash-base@3.1.0: - resolution: {integrity: sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==} - engines: {node: '>=4'} - dependencies: - inherits: 2.0.4 - readable-stream: 3.6.2 - safe-buffer: 5.2.1 - dev: true - - /hash.js@1.1.7: - resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} - dependencies: - inherits: 2.0.4 - minimalistic-assert: 1.0.1 - dev: true - - /hasown@2.0.2: - resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} - engines: {node: '>= 0.4'} - dependencies: - function-bind: 1.1.2 - dev: true - - /he@1.2.0: - resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} - hasBin: true - dev: true - - /heap@0.2.7: - resolution: {integrity: sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==} - dev: true - - /hmac-drbg@1.0.1: - resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} - dependencies: - hash.js: 1.1.7 - minimalistic-assert: 1.0.1 - minimalistic-crypto-utils: 1.0.1 - dev: true - - /html-escaper@2.0.2: - resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} - dev: true - - /http-basic@8.1.3: - resolution: {integrity: sha512-/EcDMwJZh3mABI2NhGfHOGOeOZITqfkEO4p/xK+l3NpyncIHUQBoMvCSF/b5GqvKtySC2srL/GGG3+EtlqlmCw==} - engines: {node: '>=6.0.0'} - dependencies: - caseless: 0.12.0 - concat-stream: 1.6.2 - http-response-object: 3.0.2 - parse-cache-control: 1.0.1 - dev: true - - /http-cache-semantics@4.1.1: - resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} - requiresBuild: true - optional: true - - /http-errors@2.0.0: - resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} - engines: {node: '>= 0.8'} - dependencies: - depd: 2.0.0 - inherits: 2.0.4 - setprototypeof: 1.2.0 - statuses: 2.0.1 - toidentifier: 1.0.1 - dev: true - - /http-proxy-agent@4.0.1: - resolution: {integrity: sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==} - engines: {node: '>= 6'} - requiresBuild: true - dependencies: - '@tootallnate/once': 1.1.2 - agent-base: 6.0.2 - debug: 4.3.7(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - optional: true - - /http-response-object@3.0.2: - resolution: {integrity: sha512-bqX0XTF6fnXSQcEJ2Iuyr75yVakyjIDCqroJQ/aHfSdlM743Cwqoi2nDYMzLGWUcuTWGWy8AAvOKXTfiv6q9RA==} - dependencies: - '@types/node': 10.17.60 - dev: true - - /https-proxy-agent@5.0.1: - resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} - engines: {node: '>= 6'} - dependencies: - agent-base: 6.0.2 - debug: 4.3.7(supports-color@8.1.1) - transitivePeerDependencies: - - supports-color - - /human-signals@2.1.0: - resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} - engines: {node: '>=10.17.0'} - dev: true - - /humanize-ms@1.2.1: - resolution: {integrity: sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==} - requiresBuild: true - dependencies: - ms: 2.1.3 - optional: true - - /iconv-lite@0.4.24: - resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} - engines: {node: '>=0.10.0'} - dependencies: - safer-buffer: 2.1.2 - dev: true - - /iconv-lite@0.6.3: - resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} - engines: {node: '>=0.10.0'} - requiresBuild: true - dependencies: - safer-buffer: 2.1.2 - optional: true - - /ieee754@1.2.1: - resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} - - /ignore@5.3.2: - resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} - engines: {node: '>= 4'} - dev: true - - /immer@10.0.2: - resolution: {integrity: sha512-Rx3CqeqQ19sxUtYV9CU911Vhy8/721wRFnJv3REVGWUmoAcIwzifTsdmJte/MV+0/XpM35LZdQMBGkRIoLPwQA==} - dev: true - - /immutable@4.3.7: - resolution: {integrity: sha512-1hqclzwYwjRDFLjcFxOM5AYkkG0rpFPpr1RLPMEuGczoS7YA8gLhy8SWXYRAA/XwfEHpfo3cw5JGioS32fnMRw==} - dev: true - - /import-fresh@3.3.0: - resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} - engines: {node: '>=6'} - dependencies: - parent-module: 1.0.1 - resolve-from: 4.0.0 - dev: true - - /import-local@3.2.0: - resolution: {integrity: sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==} - engines: {node: '>=8'} - hasBin: true - dependencies: - pkg-dir: 4.2.0 - resolve-cwd: 3.0.0 - dev: true - - /imul@1.0.1: - resolution: {integrity: sha512-WFAgfwPLAjU66EKt6vRdTlKj4nAgIDQzh29JonLa4Bqtl6D8JrIMvWjCnx7xEjVNmP3U0fM5o8ZObk7d0f62bA==} - engines: {node: '>=0.10.0'} - dev: true - - /imurmurhash@0.1.4: - resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} - engines: {node: '>=0.8.19'} - - /indent-string@4.0.0: - resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} - engines: {node: '>=8'} - - /infer-owner@1.0.4: - resolution: {integrity: sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==} - requiresBuild: true - optional: true - - /inflight@1.0.6: - resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} - deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. - dependencies: - once: 1.4.0 - wrappy: 1.0.2 - - /inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - - /ini@1.3.8: - resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - - /interpret@1.4.0: - resolution: {integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==} - engines: {node: '>= 0.10'} - dev: true - - /io-ts@1.10.4: - resolution: {integrity: sha512-b23PteSnYXSONJ6JQXRAlvJhuw8KOtkqa87W4wDtvMrud/DTJd5X+NpOOI+O/zZwVq6v0VLAaJ+1EDViKEuN9g==} - dependencies: - fp-ts: 1.19.3 - dev: true - - /ip-address@9.0.5: - resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==} - engines: {node: '>= 12'} - requiresBuild: true - dependencies: - jsbn: 1.1.0 - sprintf-js: 1.1.3 - optional: true - - /is-arguments@1.1.1: - resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - has-tostringtag: 1.0.2 - dev: true - - /is-arrayish@0.2.1: - resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - dev: true - - /is-binary-path@2.1.0: - resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} - engines: {node: '>=8'} - dependencies: - binary-extensions: 2.3.0 - dev: true - - /is-callable@1.2.7: - resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} - engines: {node: '>= 0.4'} - dev: true - - /is-core-module@2.15.1: - resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==} - engines: {node: '>= 0.4'} - dependencies: - hasown: 2.0.2 - dev: true - - /is-extglob@2.1.1: - resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} - engines: {node: '>=0.10.0'} - dev: true - - /is-fullwidth-code-point@2.0.0: - resolution: {integrity: sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==} - engines: {node: '>=4'} - dev: true - - /is-fullwidth-code-point@3.0.0: - resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} - engines: {node: '>=8'} - - /is-generator-fn@2.1.0: - resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} - engines: {node: '>=6'} - dev: true - - /is-generator-function@1.0.10: - resolution: {integrity: sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==} - engines: {node: '>= 0.4'} - dependencies: - has-tostringtag: 1.0.2 - dev: true - - /is-glob@4.0.3: - resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} - engines: {node: '>=0.10.0'} - dependencies: - is-extglob: 2.1.1 - dev: true - - /is-hex-prefixed@1.0.0: - resolution: {integrity: sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA==} - engines: {node: '>=6.5.0', npm: '>=3'} - dev: true - - /is-lambda@1.0.1: - resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==} - requiresBuild: true - optional: true - - /is-number@7.0.0: - resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} - engines: {node: '>=0.12.0'} - dev: true - - /is-plain-obj@2.1.0: - resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==} - engines: {node: '>=8'} - dev: true - - /is-stream@2.0.1: - resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} - engines: {node: '>=8'} - dev: true - - /is-subset@0.1.1: - resolution: {integrity: sha512-6Ybun0IkarhmEqxXCNw/C0bna6Zb/TkfUX9UbwJtK6ObwAVCxmAP308WWTHviM/zAqXk05cdhYsUsZeGQh99iw==} - dev: true - - /is-typed-array@1.1.13: - resolution: {integrity: sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==} - engines: {node: '>= 0.4'} - dependencies: - which-typed-array: 1.1.16 - dev: true - - /is-unicode-supported@0.1.0: - resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} - engines: {node: '>=10'} - dev: true - - /isarray@1.0.0: - resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} - dev: true - - /isexe@2.0.0: - resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - - /isomorphic-unfetch@3.1.0: - resolution: {integrity: sha512-geDJjpoZ8N0kWexiwkX8F9NkTsXhetLPVbZFQ+JTW239QNOwvB0gniuR1Wc6f0AMTn7/mFGyXvHTifrCp/GH8Q==} - dependencies: - node-fetch: 2.7.0 - unfetch: 4.2.0 - transitivePeerDependencies: - - encoding - dev: true - - /istanbul-lib-coverage@3.2.2: - resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} - engines: {node: '>=8'} - dev: true - - /istanbul-lib-instrument@5.2.1: - resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} - engines: {node: '>=8'} - dependencies: - '@babel/core': 7.26.0 - '@babel/parser': 7.26.3 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-coverage: 3.2.2 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: true - - /istanbul-lib-instrument@6.0.3: - resolution: {integrity: sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==} - engines: {node: '>=10'} - dependencies: - '@babel/core': 7.26.0 - '@babel/parser': 7.26.3 - '@istanbuljs/schema': 0.1.3 - istanbul-lib-coverage: 3.2.2 - semver: 7.6.3 - transitivePeerDependencies: - - supports-color - dev: true - - /istanbul-lib-report@3.0.1: - resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} - engines: {node: '>=10'} - dependencies: - istanbul-lib-coverage: 3.2.2 - make-dir: 4.0.0 - supports-color: 7.2.0 - dev: true - - /istanbul-lib-source-maps@4.0.1: - resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} - engines: {node: '>=10'} - dependencies: - debug: 4.3.7(supports-color@8.1.1) - istanbul-lib-coverage: 3.2.2 - source-map: 0.6.1 - transitivePeerDependencies: - - supports-color - dev: true - - /istanbul-reports@3.1.7: - resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} - engines: {node: '>=8'} - dependencies: - html-escaper: 2.0.2 - istanbul-lib-report: 3.0.1 - dev: true - - /jake@10.9.2: - resolution: {integrity: sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==} - engines: {node: '>=10'} - hasBin: true - dependencies: - async: 3.2.6 - chalk: 4.1.2 - filelist: 1.0.4 - minimatch: 3.1.2 - dev: true - - /javascript-natural-sort@0.7.1: - resolution: {integrity: sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==} - dev: true - - /jest-changed-files@29.7.0: - resolution: {integrity: sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - execa: 5.1.1 - jest-util: 29.7.0 - p-limit: 3.1.0 - dev: true - - /jest-circus@29.7.0: - resolution: {integrity: sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/environment': 29.7.0 - '@jest/expect': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 18.19.67 - chalk: 4.1.2 - co: 4.6.0 - dedent: 1.5.3 - is-generator-fn: 2.1.0 - jest-each: 29.7.0 - jest-matcher-utils: 29.7.0 - jest-message-util: 29.7.0 - jest-runtime: 29.7.0 - jest-snapshot: 29.7.0 - jest-util: 29.7.0 - p-limit: 3.1.0 - pretty-format: 29.7.0 - pure-rand: 6.1.0 - slash: 3.0.0 - stack-utils: 2.0.6 - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - dev: true - - /jest-cli@29.7.0(@types/node@18.19.67)(ts-node@10.9.2): - resolution: {integrity: sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - hasBin: true - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2) - '@jest/test-result': 29.7.0 - '@jest/types': 29.6.3 - chalk: 4.1.2 - create-jest: 29.7.0(@types/node@18.19.67)(ts-node@10.9.2) - exit: 0.1.2 - import-local: 3.2.0 - jest-config: 29.7.0(@types/node@18.19.67)(ts-node@10.9.2) - jest-util: 29.7.0 - jest-validate: 29.7.0 - yargs: 17.7.2 - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - dev: true - - /jest-config@29.7.0(@types/node@18.19.67)(ts-node@10.9.2): - resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - peerDependencies: - '@types/node': '*' - ts-node: '>=9.0.0' - peerDependenciesMeta: - '@types/node': - optional: true - ts-node: - optional: true - dependencies: - '@babel/core': 7.26.0 - '@jest/test-sequencer': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 18.19.67 - babel-jest: 29.7.0(@babel/core@7.26.0) - chalk: 4.1.2 - ci-info: 3.9.0 - deepmerge: 4.3.1 - glob: 7.2.3 - graceful-fs: 4.2.11 - jest-circus: 29.7.0 - jest-environment-node: 29.7.0 - jest-get-type: 29.6.3 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-runner: 29.7.0 - jest-util: 29.7.0 - jest-validate: 29.7.0 - micromatch: 4.0.8 - parse-json: 5.2.0 - pretty-format: 29.7.0 - slash: 3.0.0 - strip-json-comments: 3.1.1 - ts-node: 10.9.2(@types/node@18.19.67)(typescript@5.7.2) - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - dev: true - - /jest-diff@29.7.0: - resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - chalk: 4.1.2 - diff-sequences: 29.6.3 - jest-get-type: 29.6.3 - pretty-format: 29.7.0 - dev: true - - /jest-docblock@29.7.0: - resolution: {integrity: sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - detect-newline: 3.1.0 - dev: true - - /jest-each@29.7.0: - resolution: {integrity: sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.6.3 - chalk: 4.1.2 - jest-get-type: 29.6.3 - jest-util: 29.7.0 - pretty-format: 29.7.0 - dev: true - - /jest-environment-node@29.7.0: - resolution: {integrity: sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/environment': 29.7.0 - '@jest/fake-timers': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 18.19.67 - jest-mock: 29.7.0 - jest-util: 29.7.0 - dev: true - - /jest-get-type@29.6.3: - resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dev: true - - /jest-haste-map@29.7.0: - resolution: {integrity: sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.6.3 - '@types/graceful-fs': 4.1.9 - '@types/node': 18.19.67 - anymatch: 3.1.3 - fb-watchman: 2.0.2 - graceful-fs: 4.2.11 - jest-regex-util: 29.6.3 - jest-util: 29.7.0 - jest-worker: 29.7.0 - micromatch: 4.0.8 - walker: 1.0.8 - optionalDependencies: - fsevents: 2.3.3 - dev: true - - /jest-leak-detector@29.7.0: - resolution: {integrity: sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - jest-get-type: 29.6.3 - pretty-format: 29.7.0 - dev: true - - /jest-matcher-utils@29.7.0: - resolution: {integrity: sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - chalk: 4.1.2 - jest-diff: 29.7.0 - jest-get-type: 29.6.3 - pretty-format: 29.7.0 - dev: true - - /jest-message-util@29.7.0: - resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@babel/code-frame': 7.26.2 - '@jest/types': 29.6.3 - '@types/stack-utils': 2.0.3 - chalk: 4.1.2 - graceful-fs: 4.2.11 - micromatch: 4.0.8 - pretty-format: 29.7.0 - slash: 3.0.0 - stack-utils: 2.0.6 - dev: true - - /jest-mock@29.7.0: - resolution: {integrity: sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.6.3 - '@types/node': 18.19.67 - jest-util: 29.7.0 - dev: true - - /jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): - resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} - engines: {node: '>=6'} - peerDependencies: - jest-resolve: '*' - peerDependenciesMeta: - jest-resolve: - optional: true - dependencies: - jest-resolve: 29.7.0 - dev: true - - /jest-regex-util@29.6.3: - resolution: {integrity: sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dev: true - - /jest-resolve-dependencies@29.7.0: - resolution: {integrity: sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - jest-regex-util: 29.6.3 - jest-snapshot: 29.7.0 - transitivePeerDependencies: - - supports-color - dev: true - - /jest-resolve@29.7.0: - resolution: {integrity: sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - chalk: 4.1.2 - graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - jest-pnp-resolver: 1.2.3(jest-resolve@29.7.0) - jest-util: 29.7.0 - jest-validate: 29.7.0 - resolve: 1.22.8 - resolve.exports: 2.0.3 - slash: 3.0.0 - dev: true - - /jest-runner@29.7.0: - resolution: {integrity: sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/console': 29.7.0 - '@jest/environment': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 18.19.67 - chalk: 4.1.2 - emittery: 0.13.1 - graceful-fs: 4.2.11 - jest-docblock: 29.7.0 - jest-environment-node: 29.7.0 - jest-haste-map: 29.7.0 - jest-leak-detector: 29.7.0 - jest-message-util: 29.7.0 - jest-resolve: 29.7.0 - jest-runtime: 29.7.0 - jest-util: 29.7.0 - jest-watcher: 29.7.0 - jest-worker: 29.7.0 - p-limit: 3.1.0 - source-map-support: 0.5.13 - transitivePeerDependencies: - - supports-color - dev: true - - /jest-runtime@29.7.0: - resolution: {integrity: sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/environment': 29.7.0 - '@jest/fake-timers': 29.7.0 - '@jest/globals': 29.7.0 - '@jest/source-map': 29.6.3 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 18.19.67 - chalk: 4.1.2 - cjs-module-lexer: 1.4.1 - collect-v8-coverage: 1.0.2 - glob: 7.2.3 - graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - jest-message-util: 29.7.0 - jest-mock: 29.7.0 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-snapshot: 29.7.0 - jest-util: 29.7.0 - slash: 3.0.0 - strip-bom: 4.0.0 - transitivePeerDependencies: - - supports-color - dev: true - - /jest-snapshot@29.7.0: - resolution: {integrity: sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@babel/core': 7.26.0 - '@babel/generator': 7.26.3 - '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.0) - '@babel/plugin-syntax-typescript': 7.25.9(@babel/core@7.26.0) - '@babel/types': 7.26.3 - '@jest/expect-utils': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - babel-preset-current-node-syntax: 1.1.0(@babel/core@7.26.0) - chalk: 4.1.2 - expect: 29.7.0 - graceful-fs: 4.2.11 - jest-diff: 29.7.0 - jest-get-type: 29.6.3 - jest-matcher-utils: 29.7.0 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - natural-compare: 1.4.0 - pretty-format: 29.7.0 - semver: 7.6.3 - transitivePeerDependencies: - - supports-color - dev: true - - /jest-util@29.7.0: - resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.6.3 - '@types/node': 18.19.67 - chalk: 4.1.2 - ci-info: 3.9.0 - graceful-fs: 4.2.11 - picomatch: 2.3.1 - dev: true - - /jest-validate@29.7.0: - resolution: {integrity: sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/types': 29.6.3 - camelcase: 6.3.0 - chalk: 4.1.2 - jest-get-type: 29.6.3 - leven: 3.1.0 - pretty-format: 29.7.0 - dev: true - - /jest-watcher@29.7.0: - resolution: {integrity: sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/test-result': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 18.19.67 - ansi-escapes: 4.3.2 - chalk: 4.1.2 - emittery: 0.13.1 - jest-util: 29.7.0 - string-length: 4.0.2 - dev: true - - /jest-worker@29.7.0: - resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@types/node': 18.19.67 - jest-util: 29.7.0 - merge-stream: 2.0.0 - supports-color: 8.1.1 - dev: true - - /jest@29.7.0(@types/node@18.19.67)(ts-node@10.9.2): - resolution: {integrity: sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - hasBin: true - peerDependencies: - node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 - peerDependenciesMeta: - node-notifier: - optional: true - dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2) - '@jest/types': 29.6.3 - import-local: 3.2.0 - jest-cli: 29.7.0(@types/node@18.19.67)(ts-node@10.9.2) - transitivePeerDependencies: - - '@types/node' - - babel-plugin-macros - - supports-color - - ts-node - dev: true - - /js-cookie@2.2.1: - resolution: {integrity: sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==} - dev: true - - /js-sha3@0.8.0: - resolution: {integrity: sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==} - dev: true - - /js-tokens@4.0.0: - resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} - dev: true - - /js-yaml@3.14.1: - resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} - hasBin: true - dependencies: - argparse: 1.0.10 - esprima: 4.0.1 - dev: true - - /js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} - hasBin: true - dependencies: - argparse: 2.0.1 - dev: true - - /jsbn@1.1.0: - resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==} - requiresBuild: true - optional: true - - /jsesc@2.5.2: - resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} - engines: {node: '>=4'} - hasBin: true - dev: true - - /jsesc@3.0.2: - resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} - engines: {node: '>=6'} - hasBin: true - dev: true - - /json-buffer@3.0.1: - resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} - dev: true - - /json-parse-even-better-errors@2.3.1: - resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - dev: true - - /json-schema-traverse@0.4.1: - resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} - dev: true - - /json-schema-traverse@1.0.0: - resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} - dev: true - - /json-stable-stringify-without-jsonify@1.0.1: - resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - dev: true - - /json-stream-stringify@3.1.6: - resolution: {integrity: sha512-x7fpwxOkbhFCaJDJ8vb1fBY3DdSa4AlITaz+HHILQJzdPMnHEFjxPwVUi1ALIbcIxDE0PNe/0i7frnY8QnBQog==} - engines: {node: '>=7.10.1'} - dev: true - - /json-stringify-safe@5.0.1: - resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} - dev: true - - /json5@2.2.3: - resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} - engines: {node: '>=6'} - hasBin: true - dev: true - - /jsonfile@4.0.0: - resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} - optionalDependencies: - graceful-fs: 4.2.11 - dev: true - - /jsonfile@6.1.0: - resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} - dependencies: - universalify: 2.0.1 - optionalDependencies: - graceful-fs: 4.2.11 - dev: true - - /jsonschema@1.4.1: - resolution: {integrity: sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==} - dev: true - - /keccak@3.0.4: - resolution: {integrity: sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q==} - engines: {node: '>=10.0.0'} - requiresBuild: true - dependencies: - node-addon-api: 2.0.2 - node-gyp-build: 4.8.4 - readable-stream: 3.6.2 - dev: true - - /keyv@4.5.4: - resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - dependencies: - json-buffer: 3.0.1 - dev: true - - /kind-of@6.0.3: - resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} - engines: {node: '>=0.10.0'} - dev: true - - /kleur@3.0.3: - resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} - engines: {node: '>=6'} - dev: true - - /leven@3.1.0: - resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} - engines: {node: '>=6'} - dev: true - - /levn@0.3.0: - resolution: {integrity: sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.1.2 - type-check: 0.3.2 - dev: true - - /levn@0.4.1: - resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.2.1 - type-check: 0.4.0 - dev: true - - /lines-and-columns@1.2.4: - resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - dev: true - - /locate-path@5.0.0: - resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} - engines: {node: '>=8'} - dependencies: - p-locate: 4.1.0 - dev: true - - /locate-path@6.0.0: - resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} - engines: {node: '>=10'} - dependencies: - p-locate: 5.0.0 - dev: true - - /lodash.camelcase@4.3.0: - resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} - dev: true - - /lodash.clonedeep@4.5.0: - resolution: {integrity: sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==} - dev: true - - /lodash.isequal@4.5.0: - resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} - dev: true - - /lodash.memoize@4.1.2: - resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} - dev: true - - /lodash.merge@4.6.2: - resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - dev: true - - /lodash.truncate@4.4.2: - resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} - dev: true - - /lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - dev: true - - /log-symbols@4.1.0: - resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} - engines: {node: '>=10'} - dependencies: - chalk: 4.1.2 - is-unicode-supported: 0.1.0 - dev: true - - /loupe@2.3.7: - resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} - dependencies: - get-func-name: 2.0.2 - dev: true - - /lru-cache@10.4.3: - resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} - dev: true - - /lru-cache@5.1.1: - resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} - dependencies: - yallist: 3.1.1 - dev: true - - /lru-cache@6.0.0: - resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} - engines: {node: '>=10'} - requiresBuild: true - dependencies: - yallist: 4.0.0 - optional: true - - /lru_map@0.3.3: - resolution: {integrity: sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==} - dev: true - - /make-dir@4.0.0: - resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} - engines: {node: '>=10'} - dependencies: - semver: 7.6.3 - dev: true - - /make-error@1.3.6: - resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} - dev: true - - /make-fetch-happen@9.1.0: - resolution: {integrity: sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==} - engines: {node: '>= 10'} - requiresBuild: true - dependencies: - agentkeepalive: 4.5.0 - cacache: 15.3.0 - http-cache-semantics: 4.1.1 - http-proxy-agent: 4.0.1 - https-proxy-agent: 5.0.1 - is-lambda: 1.0.1 - lru-cache: 6.0.0 - minipass: 3.3.6 - minipass-collect: 1.0.2 - minipass-fetch: 1.4.1 - minipass-flush: 1.0.5 - minipass-pipeline: 1.2.4 - negotiator: 0.6.4 - promise-retry: 2.0.1 - socks-proxy-agent: 6.2.1 - ssri: 8.0.1 - transitivePeerDependencies: - - bluebird - - supports-color - optional: true - - /makeerror@1.0.12: - resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} - dependencies: - tmpl: 1.0.5 - dev: true - - /markdown-table@1.1.3: - resolution: {integrity: sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==} - dev: true - - /match-all@1.2.6: - resolution: {integrity: sha512-0EESkXiTkWzrQQntBu2uzKvLu6vVkUGz40nGPbSZuegcfE5UuSzNjLaIu76zJWuaT/2I3Z/8M06OlUOZLGwLlQ==} - dev: true - - /md5.js@1.3.5: - resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} - dependencies: - hash-base: 3.1.0 - inherits: 2.0.4 - safe-buffer: 5.2.1 - dev: true - - /memorystream@0.3.1: - resolution: {integrity: sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==} - engines: {node: '>= 0.10.0'} - dev: true - - /merge-stream@2.0.0: - resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} - dev: true - - /merge2@1.4.1: - resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} - engines: {node: '>= 8'} - dev: true - - /micro-ftch@0.3.1: - resolution: {integrity: sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg==} - dev: true - - /micromatch@4.0.8: - resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} - engines: {node: '>=8.6'} - dependencies: - braces: 3.0.3 - picomatch: 2.3.1 - dev: true - - /mime-db@1.52.0: - resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} - engines: {node: '>= 0.6'} - dev: true - - /mime-types@2.1.35: - resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} - engines: {node: '>= 0.6'} - dependencies: - mime-db: 1.52.0 - dev: true - - /mimic-fn@2.1.0: - resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} - engines: {node: '>=6'} - dev: true - - /mimic-response@3.1.0: - resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} - engines: {node: '>=10'} - - /minimalistic-assert@1.0.1: - resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} - dev: true - - /minimalistic-crypto-utils@1.0.1: - resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} - dev: true - - /minimatch@3.1.2: - resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} - dependencies: - brace-expansion: 1.1.11 - - /minimatch@5.1.6: - resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} - engines: {node: '>=10'} - dependencies: - brace-expansion: 2.0.1 - dev: true - - /minimatch@8.0.4: - resolution: {integrity: sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==} - engines: {node: '>=16 || 14 >=14.17'} - dependencies: - brace-expansion: 2.0.1 - dev: true - - /minimatch@9.0.5: - resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} - engines: {node: '>=16 || 14 >=14.17'} - dependencies: - brace-expansion: 2.0.1 - dev: true - - /minimist@1.2.8: - resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} - - /minipass-collect@1.0.2: - resolution: {integrity: sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==} - engines: {node: '>= 8'} - requiresBuild: true - dependencies: - minipass: 3.3.6 - optional: true - - /minipass-fetch@1.4.1: - resolution: {integrity: sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==} - engines: {node: '>=8'} - requiresBuild: true - dependencies: - minipass: 3.3.6 - minipass-sized: 1.0.3 - minizlib: 2.1.2 - optionalDependencies: - encoding: 0.1.13 - optional: true - - /minipass-flush@1.0.5: - resolution: {integrity: sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==} - engines: {node: '>= 8'} - requiresBuild: true - dependencies: - minipass: 3.3.6 - optional: true - - /minipass-pipeline@1.2.4: - resolution: {integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==} - engines: {node: '>=8'} - requiresBuild: true - dependencies: - minipass: 3.3.6 - optional: true - - /minipass-sized@1.0.3: - resolution: {integrity: sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==} - engines: {node: '>=8'} - requiresBuild: true - dependencies: - minipass: 3.3.6 - optional: true - - /minipass@3.3.6: - resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==} - engines: {node: '>=8'} - dependencies: - yallist: 4.0.0 - - /minipass@4.2.8: - resolution: {integrity: sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==} - engines: {node: '>=8'} - dev: true - - /minipass@5.0.0: - resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} - engines: {node: '>=8'} - - /minipass@7.1.2: - resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} - engines: {node: '>=16 || 14 >=14.17'} - dev: true - - /minizlib@2.1.2: - resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==} - engines: {node: '>= 8'} - dependencies: - minipass: 3.3.6 - yallist: 4.0.0 - - /mkdirp-classic@0.5.3: - resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} - - /mkdirp@0.5.6: - resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} - hasBin: true - dependencies: - minimist: 1.2.8 - dev: true - - /mkdirp@1.0.4: - resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} - engines: {node: '>=10'} - hasBin: true - - /mnemonist@0.38.5: - resolution: {integrity: sha512-bZTFT5rrPKtPJxj8KSV0WkPyNxl72vQepqqVUAW2ARUpUSF2qXMB6jZj7hW5/k7C1rtpzqbD/IIbJwLXUjCHeg==} - dependencies: - obliterator: 2.0.4 - dev: true - - /mocha@10.8.2: - resolution: {integrity: sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==} - engines: {node: '>= 14.0.0'} - hasBin: true - dependencies: - ansi-colors: 4.1.3 - browser-stdout: 1.3.1 - chokidar: 3.6.0 - debug: 4.3.7(supports-color@8.1.1) - diff: 5.2.0 - escape-string-regexp: 4.0.0 - find-up: 5.0.0 - glob: 8.1.0 - he: 1.2.0 - js-yaml: 4.1.0 - log-symbols: 4.1.0 - minimatch: 5.1.6 - ms: 2.1.3 - serialize-javascript: 6.0.2 - strip-json-comments: 3.1.1 - supports-color: 8.1.1 - workerpool: 6.5.1 - yargs: 16.2.0 - yargs-parser: 20.2.9 - yargs-unparser: 2.0.0 - dev: true - - /ms@2.1.3: - resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} - - /murmur-128@0.2.1: - resolution: {integrity: sha512-WseEgiRkI6aMFBbj8Cg9yBj/y+OdipwVC7zUo3W2W1JAJITwouUOtpqsmGSg67EQmwwSyod7hsVsWY5LsrfQVg==} - dependencies: - encode-utf8: 1.0.3 - fmix: 0.1.0 - imul: 1.0.1 - dev: true - - /napi-build-utils@1.0.2: - resolution: {integrity: sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==} - - /natural-compare@1.4.0: - resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} - dev: true - - /ndjson@2.0.0: - resolution: {integrity: sha512-nGl7LRGrzugTtaFcJMhLbpzJM6XdivmbkdlaGcrk/LXg2KL/YBC6z1g70xh0/al+oFuVFP8N8kiWRucmeEH/qQ==} - engines: {node: '>=10'} - hasBin: true - dependencies: - json-stringify-safe: 5.0.1 - minimist: 1.2.8 - readable-stream: 3.6.2 - split2: 3.2.2 - through2: 4.0.2 - dev: true - - /negotiator@0.6.4: - resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==} - engines: {node: '>= 0.6'} - requiresBuild: true - optional: true - - /neo-async@2.6.2: - resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} - dev: true - - /node-abi@3.71.0: - resolution: {integrity: sha512-SZ40vRiy/+wRTf21hxkkEjPJZpARzUMVcJoQse2EF8qkUWbbO2z7vd5oA/H6bVH6SZQ5STGcu0KRDS7biNRfxw==} - engines: {node: '>=10'} - dependencies: - semver: 7.6.3 - - /node-addon-api@2.0.2: - resolution: {integrity: sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==} - dev: true - - /node-addon-api@5.1.0: - resolution: {integrity: sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==} - dev: true - - /node-addon-api@7.1.1: - resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==} - - /node-emoji@1.11.0: - resolution: {integrity: sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==} - dependencies: - lodash: 4.17.21 - dev: true - - /node-fetch@2.7.0: - resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} - engines: {node: 4.x || >=6.0.0} - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - dependencies: - whatwg-url: 5.0.0 - dev: true - - /node-gyp-build@4.8.4: - resolution: {integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==} - hasBin: true - dev: true - - /node-gyp@8.4.1: - resolution: {integrity: sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==} - engines: {node: '>= 10.12.0'} - hasBin: true - requiresBuild: true - dependencies: - env-paths: 2.2.1 - glob: 7.2.3 - graceful-fs: 4.2.11 - make-fetch-happen: 9.1.0 - nopt: 5.0.0 - npmlog: 6.0.2 - rimraf: 3.0.2 - semver: 7.6.3 - tar: 6.2.1 - which: 2.0.2 - transitivePeerDependencies: - - bluebird - - supports-color - optional: true - - /node-int64@0.4.0: - resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} - dev: true - - /node-interval-tree@2.1.2: - resolution: {integrity: sha512-bJ9zMDuNGzVQg1xv0bCPzyEDxHgbrx7/xGj6CDokvizZZmastPsOh0JJLuY8wA5q2SfX1TLNMk7XNV8WxbGxzA==} - engines: {node: '>= 14.0.0'} - dependencies: - shallowequal: 1.1.0 - dev: true - - /node-releases@2.0.18: - resolution: {integrity: sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==} - dev: true - - /node-tfhe@0.9.1: - resolution: {integrity: sha512-M2CbUVX4DQneaaK/4fygy9lW0zjOOzM8yGWAgbKGRt/Gd07zaloFEGGHW7dbmUaHo022q1uo7nzxyYhe4UgqCw==} - dev: true - - /node-tkms@0.9.0-rc36: - resolution: {integrity: sha512-oGqJfjvb/igd9VgQaqYbzKc+CmrnQ/eY0ShmdE3JDKXL3C4Re/tBswT0KkWmlT1aM+Lxt5ihRNOs2oHtrPqr5w==} - dev: true - - /nofilter@3.1.0: - resolution: {integrity: sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g==} - engines: {node: '>=12.19'} - dev: true - - /nopt@3.0.6: - resolution: {integrity: sha512-4GUt3kSEYmk4ITxzB/b9vaIDfUVWN/Ml1Fwl11IlnIG2iaJ9O6WXZ9SrYM9NLI8OCBieN2Y8SWC2oJV0RQ7qYg==} - hasBin: true - dependencies: - abbrev: 1.0.9 - dev: true - - /nopt@5.0.0: - resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==} - engines: {node: '>=6'} - hasBin: true - requiresBuild: true - dependencies: - abbrev: 1.1.1 - optional: true - - /normalize-path@3.0.0: - resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} - engines: {node: '>=0.10.0'} - dev: true - - /npm-run-path@4.0.1: - resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} - engines: {node: '>=8'} - dependencies: - path-key: 3.1.1 - dev: true - - /npmlog@6.0.2: - resolution: {integrity: sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - deprecated: This package is no longer supported. - requiresBuild: true - dependencies: - are-we-there-yet: 3.0.1 - console-control-strings: 1.1.0 - gauge: 4.0.4 - set-blocking: 2.0.0 - optional: true - - /number-to-bn@1.7.0: - resolution: {integrity: sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig==} - engines: {node: '>=6.5.0', npm: '>=3'} - dependencies: - bn.js: 4.11.6 - strip-hex-prefix: 1.0.0 - dev: true - - /object-assign@4.1.1: - resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} - engines: {node: '>=0.10.0'} - dev: true - - /object-inspect@1.13.3: - resolution: {integrity: sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==} - engines: {node: '>= 0.4'} - dev: true - - /obliterator@2.0.4: - resolution: {integrity: sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==} - dev: true - - /once@1.4.0: - resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} - dependencies: - wrappy: 1.0.2 - - /onetime@5.1.2: - resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} - engines: {node: '>=6'} - dependencies: - mimic-fn: 2.1.0 - dev: true - - /optionator@0.8.3: - resolution: {integrity: sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==} - engines: {node: '>= 0.8.0'} - dependencies: - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.3.0 - prelude-ls: 1.1.2 - type-check: 0.3.2 - word-wrap: 1.2.5 - dev: true - - /optionator@0.9.4: - resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} - engines: {node: '>= 0.8.0'} - dependencies: - deep-is: 0.1.4 - fast-levenshtein: 2.0.6 - levn: 0.4.1 - prelude-ls: 1.2.1 - type-check: 0.4.0 - word-wrap: 1.2.5 - dev: true - - /ordinal@1.0.3: - resolution: {integrity: sha512-cMddMgb2QElm8G7vdaa02jhUNbTSrhsgAGUz1OokD83uJTwSUn+nKoNoKVVaRa08yF6sgfO7Maou1+bgLd9rdQ==} - dev: true - - /os-tmpdir@1.0.2: - resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} - engines: {node: '>=0.10.0'} - dev: true - - /p-limit@2.3.0: - resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} - engines: {node: '>=6'} - dependencies: - p-try: 2.2.0 - dev: true - - /p-limit@3.1.0: - resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} - engines: {node: '>=10'} - dependencies: - yocto-queue: 0.1.0 - dev: true - - /p-locate@4.1.0: - resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} - engines: {node: '>=8'} - dependencies: - p-limit: 2.3.0 - dev: true - - /p-locate@5.0.0: - resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} - engines: {node: '>=10'} - dependencies: - p-limit: 3.1.0 - dev: true - - /p-map@4.0.0: - resolution: {integrity: sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==} - engines: {node: '>=10'} - dependencies: - aggregate-error: 3.1.0 - - /p-try@2.2.0: - resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} - engines: {node: '>=6'} - dev: true - - /parent-module@1.0.1: - resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} - engines: {node: '>=6'} - dependencies: - callsites: 3.1.0 - dev: true - - /parse-cache-control@1.0.1: - resolution: {integrity: sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg==} - dev: true - - /parse-json@5.2.0: - resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} - engines: {node: '>=8'} - dependencies: - '@babel/code-frame': 7.26.2 - error-ex: 1.3.2 - json-parse-even-better-errors: 2.3.1 - lines-and-columns: 1.2.4 - dev: true - - /path-exists@4.0.0: - resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} - engines: {node: '>=8'} - dev: true - - /path-is-absolute@1.0.1: - resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} - engines: {node: '>=0.10.0'} - - /path-key@3.1.1: - resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} - engines: {node: '>=8'} - dev: true - - /path-parse@1.0.7: - resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} - dev: true - - /path-scurry@1.11.1: - resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} - engines: {node: '>=16 || 14 >=14.18'} - dependencies: - lru-cache: 10.4.3 - minipass: 7.1.2 - dev: true - - /path-type@4.0.0: - resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} - engines: {node: '>=8'} - dev: true - - /pathval@1.1.1: - resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} - dev: true - - /pbkdf2@3.1.2: - resolution: {integrity: sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==} - engines: {node: '>=0.12'} - dependencies: - create-hash: 1.2.0 - create-hmac: 1.1.7 - ripemd160: 2.0.2 - safe-buffer: 5.2.1 - sha.js: 2.4.11 - dev: true - - /picocolors@1.1.1: - resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} - dev: true - - /picomatch@2.3.1: - resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} - engines: {node: '>=8.6'} - dev: true - - /picomatch@4.0.2: - resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} - engines: {node: '>=12'} - dev: true - - /pify@4.0.1: - resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} - engines: {node: '>=6'} - dev: true - - /pirates@4.0.6: - resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} - engines: {node: '>= 6'} - dev: true - - /pkg-dir@4.2.0: - resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} - engines: {node: '>=8'} - dependencies: - find-up: 4.1.0 - dev: true - - /pluralize@8.0.0: - resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==} - engines: {node: '>=4'} - dev: true - - /possible-typed-array-names@1.0.0: - resolution: {integrity: sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==} - engines: {node: '>= 0.4'} - dev: true - - /prebuild-install@7.1.2: - resolution: {integrity: sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==} - engines: {node: '>=10'} - hasBin: true - dependencies: - detect-libc: 2.0.3 - expand-template: 2.0.3 - github-from-package: 0.0.0 - minimist: 1.2.8 - mkdirp-classic: 0.5.3 - napi-build-utils: 1.0.2 - node-abi: 3.71.0 - pump: 3.0.2 - rc: 1.2.8 - simple-get: 4.0.1 - tar-fs: 2.1.1 - tunnel-agent: 0.6.0 - - /prelude-ls@1.1.2: - resolution: {integrity: sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==} - engines: {node: '>= 0.8.0'} - dev: true - - /prelude-ls@1.2.1: - resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} - engines: {node: '>= 0.8.0'} - dev: true - - /prettier-linter-helpers@1.0.0: - resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} - engines: {node: '>=6.0.0'} - dependencies: - fast-diff: 1.3.0 - dev: true - - /prettier-plugin-solidity@1.4.1(prettier@2.8.8): - resolution: {integrity: sha512-Mq8EtfacVZ/0+uDKTtHZGW3Aa7vEbX/BNx63hmVg6YTiTXSiuKP0amj0G6pGwjmLaOfymWh3QgXEZkjQbU8QRg==} - engines: {node: '>=16'} - peerDependencies: - prettier: '>=2.3.0' - dependencies: - '@solidity-parser/parser': 0.18.0 - prettier: 2.8.8 - semver: 7.6.3 - dev: true - - /prettier@2.8.8: - resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==} - engines: {node: '>=10.13.0'} - hasBin: true - dev: true - - /pretty-format@29.7.0: - resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} - engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - dependencies: - '@jest/schemas': 29.6.3 - ansi-styles: 5.2.0 - react-is: 18.3.1 - dev: true - - /process-nextick-args@2.0.1: - resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} - dev: true - - /promise-inflight@1.0.1: - resolution: {integrity: sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==} - requiresBuild: true - peerDependencies: - bluebird: '*' - peerDependenciesMeta: - bluebird: - optional: true - optional: true - - /promise-retry@2.0.1: - resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==} - engines: {node: '>=10'} - requiresBuild: true - dependencies: - err-code: 2.0.3 - retry: 0.12.0 - optional: true - - /promise@8.3.0: - resolution: {integrity: sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==} - dependencies: - asap: 2.0.6 - dev: true - - /prompts@2.4.2: - resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} - engines: {node: '>= 6'} - dependencies: - kleur: 3.0.3 - sisteransi: 1.0.5 - dev: true - - /proper-lockfile@4.1.2: - resolution: {integrity: sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==} - dependencies: - graceful-fs: 4.2.11 - retry: 0.12.0 - signal-exit: 3.0.7 - dev: true - - /proxy-from-env@1.1.0: - resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} - dev: true - - /pump@3.0.2: - resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==} - dependencies: - end-of-stream: 1.4.4 - once: 1.4.0 - - /punycode@2.3.1: - resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} - engines: {node: '>=6'} - dev: true - - /pure-rand@6.1.0: - resolution: {integrity: sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==} - dev: true - - /qs@6.13.1: - resolution: {integrity: sha512-EJPeIn0CYrGu+hli1xilKAPXODtJ12T0sP63Ijx2/khC2JtuaN3JyNIpvmnkmaEtha9ocbG4A4cMcr+TvqvwQg==} - engines: {node: '>=0.6'} - dependencies: - side-channel: 1.0.6 - dev: true - - /queue-microtask@1.2.3: - resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} - dev: true - - /randombytes@2.1.0: - resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} - dependencies: - safe-buffer: 5.2.1 - dev: true - - /raw-body@2.5.2: - resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} - engines: {node: '>= 0.8'} - dependencies: - bytes: 3.1.2 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - unpipe: 1.0.0 - dev: true - - /rc@1.2.8: - resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} - hasBin: true - dependencies: - deep-extend: 0.6.0 - ini: 1.3.8 - minimist: 1.2.8 - strip-json-comments: 2.0.1 - - /react-is@18.3.1: - resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} - dev: true - - /readable-stream@2.3.8: - resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} - dependencies: - core-util-is: 1.0.3 - inherits: 2.0.4 - isarray: 1.0.0 - process-nextick-args: 2.0.1 - safe-buffer: 5.1.2 - string_decoder: 1.1.1 - util-deprecate: 1.0.2 - dev: true - - /readable-stream@3.6.2: - resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} - engines: {node: '>= 6'} - dependencies: - inherits: 2.0.4 - string_decoder: 1.3.0 - util-deprecate: 1.0.2 - - /readdirp@3.6.0: - resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} - engines: {node: '>=8.10.0'} - dependencies: - picomatch: 2.3.1 - dev: true - - /readdirp@4.0.2: - resolution: {integrity: sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==} - engines: {node: '>= 14.16.0'} - dev: true - - /rechoir@0.6.2: - resolution: {integrity: sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==} - engines: {node: '>= 0.10'} - dependencies: - resolve: 1.22.8 - dev: true - - /recursive-readdir@2.2.3: - resolution: {integrity: sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==} - engines: {node: '>=6.0.0'} - dependencies: - minimatch: 3.1.2 - dev: true - - /reduce-flatten@2.0.0: - resolution: {integrity: sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==} - engines: {node: '>=6'} - dev: true - - /regexparam@3.0.0: - resolution: {integrity: sha512-RSYAtP31mvYLkAHrOlh25pCNQ5hWnT106VukGaaFfuJrZFkGRX5GhUAdPqpSDXxOhA2c4akmRuplv1mRqnBn6Q==} - engines: {node: '>=8'} - dev: true - - /req-cwd@2.0.0: - resolution: {integrity: sha512-ueoIoLo1OfB6b05COxAA9UpeoscNpYyM+BqYlA7H6LVF4hKGPXQQSSaD2YmvDVJMkk4UDpAHIeU1zG53IqjvlQ==} - engines: {node: '>=4'} - dependencies: - req-from: 2.0.0 - dev: true - - /req-from@2.0.0: - resolution: {integrity: sha512-LzTfEVDVQHBRfjOUMgNBA+V6DWsSnoeKzf42J7l0xa/B4jyPOuuF5MlNSmomLNGemWTnV2TIdjSSLnEn95fOQA==} - engines: {node: '>=4'} - dependencies: - resolve-from: 3.0.0 - dev: true - - /require-directory@2.1.1: - resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} - engines: {node: '>=0.10.0'} - dev: true - - /require-from-string@2.0.2: - resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} - engines: {node: '>=0.10.0'} - dev: true - - /resolve-cwd@3.0.0: - resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} - engines: {node: '>=8'} - dependencies: - resolve-from: 5.0.0 - dev: true - - /resolve-from@3.0.0: - resolution: {integrity: sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==} - engines: {node: '>=4'} - dev: true - - /resolve-from@4.0.0: - resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} - engines: {node: '>=4'} - dev: true - - /resolve-from@5.0.0: - resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} - engines: {node: '>=8'} - dev: true - - /resolve.exports@2.0.3: - resolution: {integrity: sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==} - engines: {node: '>=10'} - dev: true - - /resolve@1.1.7: - resolution: {integrity: sha512-9znBF0vBcaSN3W2j7wKvdERPwqTxSpCq+if5C0WoTCyV9n24rua28jeuQ2pL/HOf+yUe/Mef+H/5p60K0Id3bg==} - dev: true - - /resolve@1.17.0: - resolution: {integrity: sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==} - dependencies: - path-parse: 1.0.7 - dev: true - - /resolve@1.22.8: - resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} - hasBin: true - dependencies: - is-core-module: 2.15.1 - path-parse: 1.0.7 - supports-preserve-symlinks-flag: 1.0.0 - dev: true - - /retry@0.12.0: - resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} - engines: {node: '>= 4'} - - /retry@0.13.1: - resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} - engines: {node: '>= 4'} - dev: true - - /reusify@1.0.4: - resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} - engines: {iojs: '>=1.0.0', node: '>=0.10.0'} - dev: true - - /rimraf@3.0.2: - resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} - deprecated: Rimraf versions prior to v4 are no longer supported - hasBin: true - requiresBuild: true - dependencies: - glob: 7.2.3 - optional: true - - /rimraf@4.4.1: - resolution: {integrity: sha512-Gk8NlF062+T9CqNGn6h4tls3k6T1+/nXdOcSZVikNVtlRdYpA7wRJJMoXmuvOnLW844rPjdQ7JgXCYM6PPC/og==} - engines: {node: '>=14'} - hasBin: true - dependencies: - glob: 9.3.5 - dev: true - - /ripemd160@2.0.2: - resolution: {integrity: sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==} - dependencies: - hash-base: 3.1.0 - inherits: 2.0.4 - dev: true - - /rlp@2.2.7: - resolution: {integrity: sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ==} - hasBin: true - dependencies: - bn.js: 5.2.1 - dev: true - - /run-parallel@1.2.0: - resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} - dependencies: - queue-microtask: 1.2.3 - dev: true - - /safe-buffer@5.1.2: - resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} - dev: true - - /safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - - /safer-buffer@2.1.2: - resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} - - /sc-istanbul@0.4.6: - resolution: {integrity: sha512-qJFF/8tW/zJsbyfh/iT/ZM5QNHE3CXxtLJbZsL+CzdJLBsPD7SedJZoUA4d8iAcN2IoMp/Dx80shOOd2x96X/g==} - hasBin: true - dependencies: - abbrev: 1.0.9 - async: 1.5.2 - escodegen: 1.8.1 - esprima: 2.7.3 - glob: 5.0.15 - handlebars: 4.7.8 - js-yaml: 3.14.1 - mkdirp: 0.5.6 - nopt: 3.0.6 - once: 1.4.0 - resolve: 1.1.7 - supports-color: 3.2.3 - which: 1.3.1 - wordwrap: 1.0.0 - dev: true - - /scrypt-js@3.0.1: - resolution: {integrity: sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==} - dev: true - - /secp256k1@4.0.4: - resolution: {integrity: sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw==} - engines: {node: '>=18.0.0'} - requiresBuild: true - dependencies: - elliptic: 6.6.1 - node-addon-api: 5.1.0 - node-gyp-build: 4.8.4 - dev: true - - /semver@5.7.2: - resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==} - hasBin: true - dev: true - - /semver@6.3.1: - resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} - hasBin: true - dev: true - - /semver@7.6.3: - resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} - engines: {node: '>=10'} - hasBin: true - - /serialize-javascript@6.0.2: - resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} - dependencies: - randombytes: 2.1.0 - dev: true - - /set-blocking@2.0.0: - resolution: {integrity: sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==} - requiresBuild: true - optional: true - - /set-function-length@1.2.2: - resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} - engines: {node: '>= 0.4'} - dependencies: - define-data-property: 1.1.4 - es-errors: 1.3.0 - function-bind: 1.1.2 - get-intrinsic: 1.2.4 - gopd: 1.1.0 - has-property-descriptors: 1.0.2 - dev: true - - /setimmediate@1.0.5: - resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} - dev: true - - /setprototypeof@1.2.0: - resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} - dev: true - - /sha.js@2.4.11: - resolution: {integrity: sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==} - hasBin: true - dependencies: - inherits: 2.0.4 - safe-buffer: 5.2.1 - dev: true - - /sha1@1.1.1: - resolution: {integrity: sha512-dZBS6OrMjtgVkopB1Gmo4RQCDKiZsqcpAQpkV/aaj+FCrCg8r4I4qMkDPQjBgLIxlmu9k4nUbWq6ohXahOneYA==} - dependencies: - charenc: 0.0.2 - crypt: 0.0.2 - dev: true - - /sha3@2.1.4: - resolution: {integrity: sha512-S8cNxbyb0UGUM2VhRD4Poe5N58gJnJsLJ5vC7FYWGUmGhcsj4++WaIOBFVDxlG0W3To6xBuiRh+i0Qp2oNCOtg==} - dependencies: - buffer: 6.0.3 - dev: true - - /shallowequal@1.1.0: - resolution: {integrity: sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==} - dev: true - - /shebang-command@2.0.0: - resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} - engines: {node: '>=8'} - dependencies: - shebang-regex: 3.0.0 - dev: true - - /shebang-regex@3.0.0: - resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} - engines: {node: '>=8'} - dev: true - - /shelljs@0.8.5: - resolution: {integrity: sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==} - engines: {node: '>=4'} - hasBin: true - dependencies: - glob: 7.2.3 - interpret: 1.4.0 - rechoir: 0.6.2 - dev: true - - /side-channel@1.0.6: - resolution: {integrity: sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==} - engines: {node: '>= 0.4'} - dependencies: - call-bind: 1.0.7 - es-errors: 1.3.0 - get-intrinsic: 1.2.4 - object-inspect: 1.13.3 - dev: true - - /signal-exit@3.0.7: - resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} - - /simple-concat@1.0.1: - resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} - - /simple-get@4.0.1: - resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==} - dependencies: - decompress-response: 6.0.0 - once: 1.4.0 - simple-concat: 1.0.1 - - /sisteransi@1.0.5: - resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} - dev: true - - /slash@3.0.0: - resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} - engines: {node: '>=8'} - dev: true - - /slice-ansi@4.0.0: - resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - astral-regex: 2.0.0 - is-fullwidth-code-point: 3.0.0 - dev: true - - /smart-buffer@4.2.0: - resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} - engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} - requiresBuild: true - optional: true - - /socks-proxy-agent@6.2.1: - resolution: {integrity: sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==} - engines: {node: '>= 10'} - requiresBuild: true - dependencies: - agent-base: 6.0.2 - debug: 4.3.7(supports-color@8.1.1) - socks: 2.8.3 - transitivePeerDependencies: - - supports-color - optional: true - - /socks@2.8.3: - resolution: {integrity: sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==} - engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} - requiresBuild: true - dependencies: - ip-address: 9.0.5 - smart-buffer: 4.2.0 - optional: true - - /solc@0.8.26(debug@4.3.7): - resolution: {integrity: sha512-yiPQNVf5rBFHwN6SIf3TUUvVAFKcQqmSUFeq+fb6pNRCo0ZCgpYOZDi3BVoezCPIAcKrVYd/qXlBLUP9wVrZ9g==} - engines: {node: '>=10.0.0'} - hasBin: true - dependencies: - command-exists: 1.2.9 - commander: 8.3.0 - follow-redirects: 1.15.9(debug@4.3.7) - js-sha3: 0.8.0 - memorystream: 0.3.1 - semver: 5.7.2 - tmp: 0.0.33 - transitivePeerDependencies: - - debug - dev: true - - /solhint-plugin-prettier@0.0.5(prettier-plugin-solidity@1.4.1)(prettier@2.8.8): - resolution: {integrity: sha512-7jmWcnVshIrO2FFinIvDQmhQpfpS2rRRn3RejiYgnjIE68xO2bvrYvjqVNfrio4xH9ghOqn83tKuTzLjEbmGIA==} - peerDependencies: - prettier: ^1.15.0 || ^2.0.0 - prettier-plugin-solidity: ^1.0.0-alpha.14 - dependencies: - prettier: 2.8.8 - prettier-linter-helpers: 1.0.0 - prettier-plugin-solidity: 1.4.1(prettier@2.8.8) - dev: true - - /solhint@3.6.2(typescript@5.7.2): - resolution: {integrity: sha512-85EeLbmkcPwD+3JR7aEMKsVC9YrRSxd4qkXuMzrlf7+z2Eqdfm1wHWq1ffTuo5aDhoZxp2I9yF3QkxZOxOL7aQ==} - hasBin: true - dependencies: - '@solidity-parser/parser': 0.16.2 - ajv: 6.12.6 - antlr4: 4.13.2 - ast-parents: 0.0.1 - chalk: 4.1.2 - commander: 10.0.1 - cosmiconfig: 8.3.6(typescript@5.7.2) - fast-diff: 1.3.0 - glob: 8.1.0 - ignore: 5.3.2 - js-yaml: 4.1.0 - lodash: 4.17.21 - pluralize: 8.0.0 - semver: 7.6.3 - strip-ansi: 6.0.1 - table: 6.8.2 - text-table: 0.2.0 - optionalDependencies: - prettier: 2.8.8 - transitivePeerDependencies: - - typescript - dev: true - - /solidity-ast@0.4.59: - resolution: {integrity: sha512-I+CX0wrYUN9jDfYtcgWSe+OAowaXy8/1YQy7NS4ni5IBDmIYBq7ZzaP/7QqouLjzZapmQtvGLqCaYgoUWqBo5g==} - dev: true - - /solidity-comments-darwin-arm64@0.0.2: - resolution: {integrity: sha512-HidWkVLSh7v+Vu0CA7oI21GWP/ZY7ro8g8OmIxE8oTqyMwgMbE8F1yc58Sj682Hj199HCZsjmtn1BE4PCbLiGA==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /solidity-comments-darwin-x64@0.0.2: - resolution: {integrity: sha512-Zjs0Ruz6faBTPT6fBecUt6qh4CdloT8Bwoc0+qxRoTn9UhYscmbPQkUgQEbS0FQPysYqVzzxJB4h1Ofbf4wwtA==} - engines: {node: '>= 10'} - cpu: [x64] - os: [darwin] - requiresBuild: true - dev: true - optional: true - - /solidity-comments-freebsd-x64@0.0.2: - resolution: {integrity: sha512-8Qe4mpjuAxFSwZJVk7B8gAoLCdbtS412bQzBwk63L8dmlHogvE39iT70aAk3RHUddAppT5RMBunlPUCFYJ3ZTw==} - engines: {node: '>= 10'} - cpu: [x64] - os: [freebsd] - requiresBuild: true - dev: true - optional: true - - /solidity-comments-linux-arm64-gnu@0.0.2: - resolution: {integrity: sha512-spkb0MZZnmrP+Wtq4UxP+nyPAVRe82idOjqndolcNR0S9Xvu4ebwq+LvF4HiUgjTDmeiqYiFZQ8T9KGdLSIoIg==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /solidity-comments-linux-arm64-musl@0.0.2: - resolution: {integrity: sha512-guCDbHArcjE+JDXYkxx5RZzY1YF6OnAKCo+sTC5fstyW/KGKaQJNPyBNWuwYsQiaEHpvhW1ha537IvlGek8GqA==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /solidity-comments-linux-x64-gnu@0.0.2: - resolution: {integrity: sha512-zIqLehBK/g7tvrFmQljrfZXfkEeLt2v6wbe+uFu6kH/qAHZa7ybt8Vc0wYcmjo2U0PeBm15d79ee3AkwbIjFdQ==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /solidity-comments-linux-x64-musl@0.0.2: - resolution: {integrity: sha512-R9FeDloVlFGTaVkOlELDVC7+1Tjx5WBPI5L8r0AGOPHK3+jOcRh6sKYpI+VskSPDc3vOO46INkpDgUXrKydlIw==} - engines: {node: '>= 10'} - cpu: [x64] - os: [linux] - requiresBuild: true - dev: true - optional: true - - /solidity-comments-win32-arm64-msvc@0.0.2: - resolution: {integrity: sha512-QnWJoCQcJj+rnutULOihN9bixOtYWDdF5Rfz9fpHejL1BtNjdLW1om55XNVHGAHPqBxV4aeQQ6OirKnp9zKsug==} - engines: {node: '>= 10'} - cpu: [arm64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /solidity-comments-win32-ia32-msvc@0.0.2: - resolution: {integrity: sha512-vUg4nADtm/NcOtlIymG23NWJUSuMsvX15nU7ynhGBsdKtt8xhdP3C/zA6vjDk8Jg+FXGQL6IHVQ++g/7rSQi0w==} - engines: {node: '>= 10'} - cpu: [ia32] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /solidity-comments-win32-x64-msvc@0.0.2: - resolution: {integrity: sha512-36j+KUF4V/y0t3qatHm/LF5sCUCBx2UndxE1kq5bOzh/s+nQgatuyB+Pd5BfuPQHdWu2KaExYe20FlAa6NL7+Q==} - engines: {node: '>= 10'} - cpu: [x64] - os: [win32] - requiresBuild: true - dev: true - optional: true - - /solidity-comments@0.0.2: - resolution: {integrity: sha512-G+aK6qtyUfkn1guS8uzqUeua1dURwPlcOjoTYW/TwmXAcE7z/1+oGCfZUdMSe4ZMKklNbVZNiG5ibnF8gkkFfw==} - engines: {node: '>= 12'} - optionalDependencies: - solidity-comments-darwin-arm64: 0.0.2 - solidity-comments-darwin-x64: 0.0.2 - solidity-comments-freebsd-x64: 0.0.2 - solidity-comments-linux-arm64-gnu: 0.0.2 - solidity-comments-linux-arm64-musl: 0.0.2 - solidity-comments-linux-x64-gnu: 0.0.2 - solidity-comments-linux-x64-musl: 0.0.2 - solidity-comments-win32-arm64-msvc: 0.0.2 - solidity-comments-win32-ia32-msvc: 0.0.2 - solidity-comments-win32-x64-msvc: 0.0.2 - dev: true - - /solidity-coverage@0.8.12(hardhat@2.22.17): - resolution: {integrity: sha512-8cOB1PtjnjFRqOgwFiD8DaUsYJtVJ6+YdXQtSZDrLGf8cdhhh8xzTtGzVTGeBf15kTv0v7lYPJlV/az7zLEPJw==} - hasBin: true - peerDependencies: - hardhat: ^2.11.0 - dependencies: - '@ethersproject/abi': 5.7.0 - '@solidity-parser/parser': 0.18.0 - chalk: 2.4.2 - death: 1.1.0 - difflib: 0.2.4 - fs-extra: 8.1.0 - ghost-testrpc: 0.0.2 - global-modules: 2.0.0 - globby: 10.0.2 - hardhat: 2.22.17(ts-node@10.9.2)(typescript@5.7.2) - jsonschema: 1.4.1 - lodash: 4.17.21 - mocha: 10.8.2 - node-emoji: 1.11.0 - pify: 4.0.1 - recursive-readdir: 2.2.3 - sc-istanbul: 0.4.6 - semver: 7.6.3 - shelljs: 0.8.5 - web3-utils: 1.10.4 - dev: true - - /source-map-support@0.5.13: - resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} - dependencies: - buffer-from: 1.1.2 - source-map: 0.6.1 - dev: true - - /source-map-support@0.5.21: - resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} - dependencies: - buffer-from: 1.1.2 - source-map: 0.6.1 - dev: true - - /source-map@0.2.0: - resolution: {integrity: sha512-CBdZ2oa/BHhS4xj5DlhjWNHcan57/5YuvfdLf17iVmIpd9KRm+DFLmC6nBNj+6Ua7Kt3TmOjDpQT1aTYOQtoUA==} - engines: {node: '>=0.8.0'} - requiresBuild: true - dependencies: - amdefine: 1.0.1 - dev: true - optional: true - - /source-map@0.5.7: - resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} - engines: {node: '>=0.10.0'} - dev: true - - /source-map@0.6.1: - resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} - engines: {node: '>=0.10.0'} - dev: true - - /split2@3.2.2: - resolution: {integrity: sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==} - dependencies: - readable-stream: 3.6.2 - dev: true - - /sprintf-js@1.0.3: - resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} - dev: true - - /sprintf-js@1.1.3: - resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} - requiresBuild: true - optional: true - - /sqlite3@5.1.7: - resolution: {integrity: sha512-GGIyOiFaG+TUra3JIfkI/zGP8yZYLPQ0pl1bH+ODjiX57sPhrLU5sQJn1y9bDKZUFYkX1crlrPfSYt0BKKdkog==} - requiresBuild: true - dependencies: - bindings: 1.5.0 - node-addon-api: 7.1.1 - prebuild-install: 7.1.2 - tar: 6.2.1 - optionalDependencies: - node-gyp: 8.4.1 - transitivePeerDependencies: - - bluebird - - supports-color - - /ssri@8.0.1: - resolution: {integrity: sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==} - engines: {node: '>= 8'} - requiresBuild: true - dependencies: - minipass: 3.3.6 - optional: true - - /stack-utils@2.0.6: - resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} - engines: {node: '>=10'} - dependencies: - escape-string-regexp: 2.0.0 - dev: true - - /stacktrace-parser@0.1.10: - resolution: {integrity: sha512-KJP1OCML99+8fhOHxwwzyWrlUuVX5GQ0ZpJTd1DFXhdkrvg1szxfHhawXUZ3g9TkXORQd4/WG68jMlQZ2p8wlg==} - engines: {node: '>=6'} - dependencies: - type-fest: 0.7.1 - dev: true - - /statuses@2.0.1: - resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} - engines: {node: '>= 0.8'} - dev: true - - /string-format@2.0.0: - resolution: {integrity: sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA==} - dev: true - - /string-length@4.0.2: - resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} - engines: {node: '>=10'} - dependencies: - char-regex: 1.0.2 - strip-ansi: 6.0.1 - dev: true - - /string-width@2.1.1: - resolution: {integrity: sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==} - engines: {node: '>=4'} - dependencies: - is-fullwidth-code-point: 2.0.0 - strip-ansi: 4.0.0 - dev: true - - /string-width@4.2.3: - resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} - engines: {node: '>=8'} - dependencies: - emoji-regex: 8.0.0 - is-fullwidth-code-point: 3.0.0 - strip-ansi: 6.0.1 - - /string_decoder@1.1.1: - resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} - dependencies: - safe-buffer: 5.1.2 - dev: true - - /string_decoder@1.3.0: - resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} - dependencies: - safe-buffer: 5.2.1 - - /strip-ansi@4.0.0: - resolution: {integrity: sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==} - engines: {node: '>=4'} - dependencies: - ansi-regex: 3.0.1 - dev: true - - /strip-ansi@6.0.1: - resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} - engines: {node: '>=8'} - dependencies: - ansi-regex: 5.0.1 - - /strip-bom@4.0.0: - resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} - engines: {node: '>=8'} - dev: true - - /strip-final-newline@2.0.0: - resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} - engines: {node: '>=6'} - dev: true - - /strip-hex-prefix@1.0.0: - resolution: {integrity: sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A==} - engines: {node: '>=6.5.0', npm: '>=3'} - dependencies: - is-hex-prefixed: 1.0.0 - dev: true - - /strip-json-comments@2.0.1: - resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} - engines: {node: '>=0.10.0'} - - /strip-json-comments@3.1.1: - resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} - engines: {node: '>=8'} - dev: true - - /supports-color@3.2.3: - resolution: {integrity: sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A==} - engines: {node: '>=0.8.0'} - dependencies: - has-flag: 1.0.0 - dev: true - - /supports-color@5.5.0: - resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} - engines: {node: '>=4'} - dependencies: - has-flag: 3.0.0 - dev: true - - /supports-color@7.2.0: - resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} - engines: {node: '>=8'} - dependencies: - has-flag: 4.0.0 - dev: true - - /supports-color@8.1.1: - resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} - engines: {node: '>=10'} - dependencies: - has-flag: 4.0.0 - - /supports-preserve-symlinks-flag@1.0.0: - resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} - engines: {node: '>= 0.4'} - dev: true - - /sync-request@6.1.0: - resolution: {integrity: sha512-8fjNkrNlNCrVc/av+Jn+xxqfCjYaBoHqCsDz6mt030UMxJGr+GSfCV1dQt2gRtlL63+VPidwDVLr7V2OcTSdRw==} - engines: {node: '>=8.0.0'} - dependencies: - http-response-object: 3.0.2 - sync-rpc: 1.3.6 - then-request: 6.0.2 - dev: true - - /sync-rpc@1.3.6: - resolution: {integrity: sha512-J8jTXuZzRlvU7HemDgHi3pGnh/rkoqR/OZSjhTyyZrEkkYQbk7Z33AXp37mkPfPpfdOuj7Ex3H/TJM1z48uPQw==} - dependencies: - get-port: 3.2.0 - dev: true - - /table-layout@1.0.2: - resolution: {integrity: sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A==} - engines: {node: '>=8.0.0'} - dependencies: - array-back: 4.0.2 - deep-extend: 0.6.0 - typical: 5.2.0 - wordwrapjs: 4.0.1 - dev: true - - /table@6.8.2: - resolution: {integrity: sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA==} - engines: {node: '>=10.0.0'} - dependencies: - ajv: 8.17.1 - lodash.truncate: 4.4.2 - slice-ansi: 4.0.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - dev: true - - /tar-fs@2.1.1: - resolution: {integrity: sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==} - dependencies: - chownr: 1.1.4 - mkdirp-classic: 0.5.3 - pump: 3.0.2 - tar-stream: 2.2.0 - - /tar-stream@2.2.0: - resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} - engines: {node: '>=6'} - dependencies: - bl: 4.1.0 - end-of-stream: 1.4.4 - fs-constants: 1.0.0 - inherits: 2.0.4 - readable-stream: 3.6.2 - - /tar@6.2.1: - resolution: {integrity: sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==} - engines: {node: '>=10'} - dependencies: - chownr: 2.0.0 - fs-minipass: 2.1.0 - minipass: 5.0.0 - minizlib: 2.1.2 - mkdirp: 1.0.4 - yallist: 4.0.0 - - /test-exclude@6.0.0: - resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} - engines: {node: '>=8'} - dependencies: - '@istanbuljs/schema': 0.1.3 - glob: 7.2.3 - minimatch: 3.1.2 - dev: true - - /text-table@0.2.0: - resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} - dev: true - - /tfhe@0.9.1: - resolution: {integrity: sha512-kmtl7KfCCZJaFhm9lUYsTtat+yT0qzOiO6bOidM2Pt7/7jptkbS2/myeGHxb9qi2/aJ30g2joo1euKZPa207tg==} - dev: true - - /then-request@6.0.2: - resolution: {integrity: sha512-3ZBiG7JvP3wbDzA9iNY5zJQcHL4jn/0BWtXIkagfz7QgOL/LqjCEOBQuJNZfu0XYnv5JhKh+cDxCPM4ILrqruA==} - engines: {node: '>=6.0.0'} - dependencies: - '@types/concat-stream': 1.6.1 - '@types/form-data': 0.0.33 - '@types/node': 8.10.66 - '@types/qs': 6.9.17 - caseless: 0.12.0 - concat-stream: 1.6.2 - form-data: 2.5.2 - http-basic: 8.1.3 - http-response-object: 3.0.2 - promise: 8.3.0 - qs: 6.13.1 - dev: true - - /through2@4.0.2: - resolution: {integrity: sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==} - dependencies: - readable-stream: 3.6.2 - dev: true - - /tinyglobby@0.2.10: - resolution: {integrity: sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew==} - engines: {node: '>=12.0.0'} - dependencies: - fdir: 6.4.2(picomatch@4.0.2) - picomatch: 4.0.2 - dev: true - - /tkms@0.9.0-rc36: - resolution: {integrity: sha512-8IoRi6mYgnrmwTNBe/ejvHOFRhs5M6o2Ls2RVXCgAzSVBBBWJC1O8hquqlciHfME/VooUD4iokzEaBfADvoXZw==} - dev: true - - /tmp@0.0.33: - resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} - engines: {node: '>=0.6.0'} - dependencies: - os-tmpdir: 1.0.2 - dev: true - - /tmpl@1.0.5: - resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} - dev: true - - /to-fast-properties@2.0.0: - resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} - engines: {node: '>=4'} - dev: true - - /to-regex-range@5.0.1: - resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} - engines: {node: '>=8.0'} - dependencies: - is-number: 7.0.0 - dev: true - - /toidentifier@1.0.1: - resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} - engines: {node: '>=0.6'} - dev: true - - /tr46@0.0.3: - resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - dev: true - - /ts-api-utils@1.4.3(typescript@5.7.2): - resolution: {integrity: sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==} - engines: {node: '>=16'} - peerDependencies: - typescript: '>=4.2.0' - dependencies: - typescript: 5.7.2 - dev: true - - /ts-command-line-args@2.5.1: - resolution: {integrity: sha512-H69ZwTw3rFHb5WYpQya40YAX2/w7Ut75uUECbgBIsLmM+BNuYnxsltfyyLMxy6sEeKxgijLTnQtLd0nKd6+IYw==} - hasBin: true - dependencies: - chalk: 4.1.2 - command-line-args: 5.2.1 - command-line-usage: 6.1.3 - string-format: 2.0.0 - dev: true - - /ts-essentials@1.0.4: - resolution: {integrity: sha512-q3N1xS4vZpRouhYHDPwO0bDW3EZ6SK9CrrDHxi/D6BPReSjpVgWIOpLS2o0gSBZm+7q/wyKp6RVM1AeeW7uyfQ==} - dev: true - - /ts-essentials@7.0.3(typescript@5.7.2): - resolution: {integrity: sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ==} - peerDependencies: - typescript: '>=3.7.0' - dependencies: - typescript: 5.7.2 - dev: true - - /ts-generator@0.1.1: - resolution: {integrity: sha512-N+ahhZxTLYu1HNTQetwWcx3so8hcYbkKBHTr4b4/YgObFTIKkOSSsaa+nal12w8mfrJAyzJfETXawbNjSfP2gQ==} - hasBin: true - dependencies: - '@types/mkdirp': 0.5.2 - '@types/prettier': 2.7.3 - '@types/resolve': 0.0.8 - chalk: 2.4.2 - glob: 7.2.3 - mkdirp: 0.5.6 - prettier: 2.8.8 - resolve: 1.22.8 - ts-essentials: 1.0.4 - dev: true - - /ts-jest@29.2.5(@babel/core@7.26.0)(jest@29.7.0)(typescript@5.7.2): - resolution: {integrity: sha512-KD8zB2aAZrcKIdGk4OwpJggeLcH1FgrICqDSROWqlnJXGCXK4Mn6FcdK2B6670Xr73lHMG1kHw8R87A0ecZ+vA==} - engines: {node: ^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0} - hasBin: true - peerDependencies: - '@babel/core': '>=7.0.0-beta.0 <8' - '@jest/transform': ^29.0.0 - '@jest/types': ^29.0.0 - babel-jest: ^29.0.0 - esbuild: '*' - jest: ^29.0.0 - typescript: '>=4.3 <6' - peerDependenciesMeta: - '@babel/core': - optional: true - '@jest/transform': - optional: true - '@jest/types': - optional: true - babel-jest: - optional: true - esbuild: - optional: true - dependencies: - '@babel/core': 7.26.0 - bs-logger: 0.2.6 - ejs: 3.1.10 - fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@18.19.67)(ts-node@10.9.2) - jest-util: 29.7.0 - json5: 2.2.3 - lodash.memoize: 4.1.2 - make-error: 1.3.6 - semver: 7.6.3 - typescript: 5.7.2 - yargs-parser: 21.1.1 - dev: true - - /ts-node@10.9.2(@types/node@18.19.67)(typescript@5.7.2): - resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} - hasBin: true - peerDependencies: - '@swc/core': '>=1.2.50' - '@swc/wasm': '>=1.2.50' - '@types/node': '*' - typescript: '>=2.7' - peerDependenciesMeta: - '@swc/core': - optional: true - '@swc/wasm': - optional: true - dependencies: - '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.11 - '@tsconfig/node12': 1.0.11 - '@tsconfig/node14': 1.0.3 - '@tsconfig/node16': 1.0.4 - '@types/node': 18.19.67 - acorn: 8.14.0 - acorn-walk: 8.3.4 - arg: 4.1.3 - create-require: 1.1.1 - diff: 4.0.2 - make-error: 1.3.6 - typescript: 5.7.2 - v8-compile-cache-lib: 3.0.1 - yn: 3.1.1 - dev: true - - /tslib@1.14.1: - resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} - dev: true - - /tslib@2.7.0: - resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==} - dev: true - - /tslib@2.8.1: - resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - dev: true - - /tsort@0.0.1: - resolution: {integrity: sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw==} - dev: true - - /tunnel-agent@0.6.0: - resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} - dependencies: - safe-buffer: 5.2.1 - - /tweetnacl-util@0.15.1: - resolution: {integrity: sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==} - dev: true - - /tweetnacl@1.0.3: - resolution: {integrity: sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==} - dev: true - - /type-check@0.3.2: - resolution: {integrity: sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.1.2 - dev: true - - /type-check@0.4.0: - resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} - engines: {node: '>= 0.8.0'} - dependencies: - prelude-ls: 1.2.1 - dev: true - - /type-detect@4.0.8: - resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} - engines: {node: '>=4'} - dev: true - - /type-detect@4.1.0: - resolution: {integrity: sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==} - engines: {node: '>=4'} - dev: true - - /type-fest@0.20.2: - resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} - engines: {node: '>=10'} - dev: true - - /type-fest@0.21.3: - resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} - engines: {node: '>=10'} - dev: true - - /type-fest@0.7.1: - resolution: {integrity: sha512-Ne2YiiGN8bmrmJJEuTWTLJR32nh/JdL1+PSicowtNb0WFpn59GK8/lfD61bVtzguz7b3PBt74nxpv/Pw5po5Rg==} - engines: {node: '>=8'} - dev: true - - /typechain@8.3.2(typescript@5.7.2): - resolution: {integrity: sha512-x/sQYr5w9K7yv3es7jo4KTX05CLxOf7TRWwoHlrjRh8H82G64g+k7VuWPJlgMo6qrjfCulOdfBjiaDtmhFYD/Q==} - hasBin: true - peerDependencies: - typescript: '>=4.3.0' - dependencies: - '@types/prettier': 2.7.3 - debug: 4.3.7(supports-color@8.1.1) - fs-extra: 7.0.1 - glob: 7.1.7 - js-sha3: 0.8.0 - lodash: 4.17.21 - mkdirp: 1.0.4 - prettier: 2.8.8 - ts-command-line-args: 2.5.1 - ts-essentials: 7.0.3(typescript@5.7.2) - typescript: 5.7.2 - transitivePeerDependencies: - - supports-color - dev: true - - /typedarray@0.0.6: - resolution: {integrity: sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==} - dev: true - - /typescript-eslint@8.17.0(eslint@9.16.0)(typescript@5.7.2): - resolution: {integrity: sha512-409VXvFd/f1br1DCbuKNFqQpXICoTB+V51afcwG1pn1a3Cp92MqAUges3YjwEdQ0cMUoCIodjVDAYzyD8h3SYA==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - peerDependencies: - eslint: ^8.57.0 || ^9.0.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - dependencies: - '@typescript-eslint/eslint-plugin': 8.17.0(@typescript-eslint/parser@8.17.0)(eslint@9.16.0)(typescript@5.7.2) - '@typescript-eslint/parser': 8.17.0(eslint@9.16.0)(typescript@5.7.2) - '@typescript-eslint/utils': 8.17.0(eslint@9.16.0)(typescript@5.7.2) - eslint: 9.16.0 - typescript: 5.7.2 - transitivePeerDependencies: - - supports-color - dev: true - - /typescript@5.7.2: - resolution: {integrity: sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==} - engines: {node: '>=14.17'} - hasBin: true - dev: true - - /typical@4.0.0: - resolution: {integrity: sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==} - engines: {node: '>=8'} - dev: true - - /typical@5.2.0: - resolution: {integrity: sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==} - engines: {node: '>=8'} - dev: true - - /uglify-js@3.19.3: - resolution: {integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==} - engines: {node: '>=0.8.0'} - hasBin: true - requiresBuild: true - dev: true - optional: true - - /undici-types@5.26.5: - resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} - dev: true - - /undici-types@6.19.8: - resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} - dev: true - - /undici@5.28.4: - resolution: {integrity: sha512-72RFADWFqKmUb2hmmvNODKL3p9hcB6Gt2DOQMis1SEBaV6a4MH8soBvzg+95CYhCKPFedut2JY9bMfrDl9D23g==} - engines: {node: '>=14.0'} - dependencies: - '@fastify/busboy': 2.1.1 - dev: true - - /undici@6.21.0: - resolution: {integrity: sha512-BUgJXc752Kou3oOIuU1i+yZZypyZRqNPW0vqoMPl8VaoalSfeR0D8/t4iAS3yirs79SSMTxTag+ZC86uswv+Cw==} - engines: {node: '>=18.17'} - dev: true - - /unfetch@4.2.0: - resolution: {integrity: sha512-F9p7yYCn6cIW9El1zi0HI6vqpeIvBsr3dSuRO6Xuppb1u5rXpCPmMvLSyECLhybr9isec8Ohl0hPekMVrEinDA==} - dev: true - - /unique-filename@1.1.1: - resolution: {integrity: sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==} - requiresBuild: true - dependencies: - unique-slug: 2.0.2 - optional: true - - /unique-slug@2.0.2: - resolution: {integrity: sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==} - requiresBuild: true - dependencies: - imurmurhash: 0.1.4 - optional: true - - /universalify@0.1.2: - resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} - engines: {node: '>= 4.0.0'} - dev: true - - /universalify@2.0.1: - resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} - engines: {node: '>= 10.0.0'} - dev: true - - /unpipe@1.0.0: - resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} - engines: {node: '>= 0.8'} - dev: true - - /update-browserslist-db@1.1.1(browserslist@4.24.2): - resolution: {integrity: sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - dependencies: - browserslist: 4.24.2 - escalade: 3.2.0 - picocolors: 1.1.1 - dev: true - - /uri-js@4.4.1: - resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - dependencies: - punycode: 2.3.1 - dev: true - - /utf8@3.0.0: - resolution: {integrity: sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==} - dev: true - - /util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - - /util@0.12.5: - resolution: {integrity: sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==} - dependencies: - inherits: 2.0.4 - is-arguments: 1.1.1 - is-generator-function: 1.0.10 - is-typed-array: 1.1.13 - which-typed-array: 1.1.16 - dev: true - - /uuid@8.3.2: - resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} - hasBin: true - dev: true - - /v8-compile-cache-lib@3.0.1: - resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} - dev: true - - /v8-to-istanbul@9.3.0: - resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==} - engines: {node: '>=10.12.0'} - dependencies: - '@jridgewell/trace-mapping': 0.3.25 - '@types/istanbul-lib-coverage': 2.0.6 - convert-source-map: 2.0.0 - dev: true - - /walker@1.0.8: - resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} - dependencies: - makeerror: 1.0.12 - dev: true - - /wasm-feature-detect@1.8.0: - resolution: {integrity: sha512-zksaLKM2fVlnB5jQQDqKXXwYHLQUVH9es+5TOOHwGOVJOCeRBCiPjwSg+3tN2AdTCzjgli4jijCH290kXb/zWQ==} - dev: true - - /web3-errors@1.3.1: - resolution: {integrity: sha512-w3NMJujH+ZSW4ltIZZKtdbkbyQEvBzyp3JRn59Ckli0Nz4VMsVq8aF1bLWM7A2kuQ+yVEm3ySeNU+7mSRwx7RQ==} - engines: {node: '>=14', npm: '>=6.12.0'} - dependencies: - web3-types: 1.10.0 - dev: true - - /web3-types@1.10.0: - resolution: {integrity: sha512-0IXoaAFtFc8Yin7cCdQfB9ZmjafrbP6BO0f0KT/khMhXKUpoJ6yShrVhiNpyRBo8QQjuOagsWzwSK2H49I7sbw==} - engines: {node: '>=14', npm: '>=6.12.0'} - dev: true - - /web3-utils@1.10.4: - resolution: {integrity: sha512-tsu8FiKJLk2PzhDl9fXbGUWTkkVXYhtTA+SmEFkKft+9BgwLxfCRpU96sWv7ICC8zixBNd3JURVoiR3dUXgP8A==} - engines: {node: '>=8.0.0'} - dependencies: - '@ethereumjs/util': 8.1.0 - bn.js: 5.2.1 - ethereum-bloom-filters: 1.2.0 - ethereum-cryptography: 2.2.1 - ethjs-unit: 0.1.6 - number-to-bn: 1.7.0 - randombytes: 2.1.0 - utf8: 3.0.0 - dev: true - - /web3-validator@2.0.6: - resolution: {integrity: sha512-qn9id0/l1bWmvH4XfnG/JtGKKwut2Vokl6YXP5Kfg424npysmtRLe9DgiNBM9Op7QL/aSiaA0TVXibuIuWcizg==} - engines: {node: '>=14', npm: '>=6.12.0'} - dependencies: - ethereum-cryptography: 2.2.1 - util: 0.12.5 - web3-errors: 1.3.1 - web3-types: 1.10.0 - zod: 3.23.8 - dev: true - - /webidl-conversions@3.0.1: - resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - dev: true - - /whatwg-url@5.0.0: - resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} - dependencies: - tr46: 0.0.3 - webidl-conversions: 3.0.1 - dev: true - - /which-typed-array@1.1.16: - resolution: {integrity: sha512-g+N+GAWiRj66DngFwHvISJd+ITsyphZvD1vChfVg6cEdnzy53GzB3oy0fUNlvhz7H7+MiqhYr26qxQShCpKTTQ==} - engines: {node: '>= 0.4'} - dependencies: - available-typed-arrays: 1.0.7 - call-bind: 1.0.7 - for-each: 0.3.3 - gopd: 1.1.0 - has-tostringtag: 1.0.2 - dev: true - - /which@1.3.1: - resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} - hasBin: true - dependencies: - isexe: 2.0.0 - dev: true - - /which@2.0.2: - resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} - engines: {node: '>= 8'} - hasBin: true - dependencies: - isexe: 2.0.0 - - /wide-align@1.1.5: - resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} - requiresBuild: true - dependencies: - string-width: 4.2.3 - optional: true - - /widest-line@3.1.0: - resolution: {integrity: sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==} - engines: {node: '>=8'} - dependencies: - string-width: 4.2.3 - dev: true - - /word-wrap@1.2.5: - resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} - engines: {node: '>=0.10.0'} - dev: true - - /wordwrap@1.0.0: - resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} - dev: true - - /wordwrapjs@4.0.1: - resolution: {integrity: sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA==} - engines: {node: '>=8.0.0'} - dependencies: - reduce-flatten: 2.0.0 - typical: 5.2.0 - dev: true - - /workerpool@6.5.1: - resolution: {integrity: sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==} - dev: true - - /wrap-ansi@7.0.0: - resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} - engines: {node: '>=10'} - dependencies: - ansi-styles: 4.3.0 - string-width: 4.2.3 - strip-ansi: 6.0.1 - dev: true - - /wrappy@1.0.2: - resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - - /write-file-atomic@4.0.2: - resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} - engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - dependencies: - imurmurhash: 0.1.4 - signal-exit: 3.0.7 - dev: true - - /ws@7.4.6: - resolution: {integrity: sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==} - engines: {node: '>=8.3.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - dev: true - - /ws@7.5.10: - resolution: {integrity: sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==} - engines: {node: '>=8.3.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ^5.0.2 - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - dev: true - - /ws@8.17.1: - resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==} - engines: {node: '>=10.0.0'} - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: '>=5.0.2' - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - dev: true - - /y18n@5.0.8: - resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} - engines: {node: '>=10'} - dev: true - - /yallist@3.1.1: - resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} - dev: true - - /yallist@4.0.0: - resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} - - /yargs-parser@20.2.9: - resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} - engines: {node: '>=10'} - dev: true - - /yargs-parser@21.1.1: - resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} - engines: {node: '>=12'} - dev: true - - /yargs-unparser@2.0.0: - resolution: {integrity: sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==} - engines: {node: '>=10'} - dependencies: - camelcase: 6.3.0 - decamelize: 4.0.0 - flat: 5.0.2 - is-plain-obj: 2.1.0 - dev: true - - /yargs@16.2.0: - resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} - engines: {node: '>=10'} - dependencies: - cliui: 7.0.4 - escalade: 3.2.0 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 20.2.9 - dev: true - - /yargs@17.7.2: - resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} - engines: {node: '>=12'} - dependencies: - cliui: 8.0.1 - escalade: 3.2.0 - get-caller-file: 2.0.5 - require-directory: 2.1.1 - string-width: 4.2.3 - y18n: 5.0.8 - yargs-parser: 21.1.1 - dev: true - - /yn@3.1.1: - resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} - engines: {node: '>=6'} - dev: true - - /yocto-queue@0.1.0: - resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} - engines: {node: '>=10'} - dev: true - - /zksync-ethers@5.10.0(ethers@5.7.2): - resolution: {integrity: sha512-OAjTGAHF9wbdkRGkj7XZuF/a1Sk/FVbwH4pmLjAKlR7mJ7sQtQhBhrPU2dCc67xLaNvEESPfwil19ES5wooYFg==} - engines: {node: '>=16.0.0'} - peerDependencies: - ethers: ~5.7.0 - dependencies: - ethers: 5.7.2 - dev: true - - /zod@3.23.8: - resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} - dev: true diff --git a/contracts/tasks/accounts.ts b/contracts/tasks/accounts.ts deleted file mode 100644 index 2ca9e7a..0000000 --- a/contracts/tasks/accounts.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { task, types } from "hardhat/config"; - -import { ACCOUNT_NAMES } from "../test/constants"; - -task("get-accounts", "Prints the list of accounts") - .addParam("numAccounts", "Number of accounts to return (1-10)", 3, types.int) - .setAction(async ({ numAccounts }, hre) => { - // Validate input - if (numAccounts < 1 || numAccounts > 10) { - throw new Error("Number of accounts must be between 1 and 10"); - } - - // Get signers from hardhat - const signers = await hre.ethers.getSigners(); - const accounts = []; - const { mnemonic } = hre.network.config.accounts; - - // Get details for specified number of accounts - for (let i = 0; i < numAccounts && i < signers.length; i++) { - const signer = signers[i]; - const address = await signer.getAddress(); - const phrase = hre.ethers.Mnemonic.fromPhrase(mnemonic); - const pathDeployer = "m/44'/60'/0'/0/" + i; - const privateKey = hre.ethers.HDNodeWallet.fromMnemonic(phrase, pathDeployer).privateKey; - - accounts.push({ - index: i, - privateKey: privateKey, - address: address, - }); - } - console.info("\nAccount Details:"); - console.info("================"); - accounts.forEach(({ index, privateKey, address }) => { - console.info(`\nAccount ${index}: (${ACCOUNT_NAMES[index]})`); - console.info(`Address: ${address}`); - console.info(`Private Key: ${privateKey}`); - }); - }); diff --git a/contracts/tasks/mint.ts b/contracts/tasks/mint.ts deleted file mode 100644 index ee7b70e..0000000 --- a/contracts/tasks/mint.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { task } from "hardhat/config"; -import type { TaskArguments } from "hardhat/types"; -import { HardhatRuntimeEnvironment } from "hardhat/types"; - -task("task:deployConfidentialERC20").setAction(async function (taskArguments: TaskArguments, { ethers }) { - const signers = await ethers.getSigners(); - const erc20Factory = await ethers.getContractFactory("MyConfidentialERC20"); - const erc20 = await erc20Factory.connect(signers[0]).deploy("Naraggara", "NARA"); - await erc20.waitForDeployment(); - console.log("ConfidentialERC20 deployed to: ", await erc20.getAddress()); -}); - -task("task:mint") - .addParam("mint", "Tokens to mint") - .setAction(async function (taskArguments: TaskArguments, hre: HardhatRuntimeEnvironment) { - const { ethers, deployments } = hre; - const ERC20 = await deployments.get("MyConfidentialERC20"); - - const signers = await ethers.getSigners(); - - const erc20 = (await ethers.getContractAt("MyConfidentialERC20", ERC20.address)) as any; - - const tx = await erc20.connect(signers[0]).mint(+taskArguments.mint); - const rcpt = await tx.wait(); - console.log("Mint tx hash: ", rcpt.hash); - console.log("Mint done: ", taskArguments.mint, "tokens were minted succesfully"); - }); diff --git a/contracts/test/asyncDecrypt.ts b/contracts/test/asyncDecrypt.ts deleted file mode 100644 index a06adb9..0000000 --- a/contracts/test/asyncDecrypt.ts +++ /dev/null @@ -1,251 +0,0 @@ -import { Wallet } from "ethers"; -import { Contract } from "ethers"; -import { ethers, network } from "hardhat"; - -import gatewayArtifact from "../node_modules/fhevm-core-contracts/artifacts/gateway/GatewayContract.sol/GatewayContract.json"; -import { ACL_ADDRESS, GATEWAYCONTRACT_ADDRESS, KMSVERIFIER_ADDRESS, PRIVATE_KEY_KMS_SIGNER } from "./constants"; -import { awaitCoprocessor, getClearText } from "./coprocessorUtils"; -import { waitNBlocks } from "./utils"; - -const networkName = network.name; - -const aclAdd = ACL_ADDRESS; - -const CiphertextType = { - 0: "bool", - 1: "uint8", // corresponding to euint4 - 2: "uint8", // corresponding to euint8 - 3: "uint16", - 4: "uint32", - 5: "uint64", - 6: "uint128", - 7: "address", - 8: "uint256", - 9: "bytes", - 10: "bytes", - 11: "bytes", -}; - -let initNull = false; -async function impersonateNullAddress() { - // for mocked mode - const nullAddress = "0x0000000000000000000000000000000000000000"; - await network.provider.request({ - method: "hardhat_impersonateAccount", - params: [nullAddress], - }); - if (!initNull) { - await network.provider.send("hardhat_setBalance", [ - nullAddress, - "0x56BC75E2D63100000", // 100 ETH in hex - ]); - initNull = true; - } - const nullSigner = await ethers.getSigner(nullAddress); - return nullSigner; -} - -const currentTime = (): string => { - const now = new Date(); - return now.toLocaleTimeString("en-US", { hour12: true, hour: "numeric", minute: "numeric", second: "numeric" }); -}; - -const argEvents = - "(uint256 indexed requestID, uint256[] cts, address contractCaller, bytes4 callbackSelector, uint256 msgValue, uint256 maxTimestamp, bool passSignaturesToCaller)"; -const ifaceEventDecryption = new ethers.Interface(["event EventDecryption" + argEvents]); - -const argEvents2 = "(uint256 indexed requestID, bool success, bytes result)"; -const ifaceResultCallback = new ethers.Interface(["event ResultCallback" + argEvents2]); - -let gateway: Contract; -let firstBlockListening: number; -let lastBlockSnapshotForDecrypt: number; - -export const initGateway = async (): Promise => { - firstBlockListening = await ethers.provider.getBlockNumber(); - if (networkName === "hardhat" && hre.__SOLIDITY_COVERAGE_RUNNING !== true) { - // evm_snapshot is not supported in coverage mode - await ethers.provider.send("set_lastBlockSnapshotForDecrypt", [firstBlockListening]); - } - // this function will emit logs for every request and fulfilment of a decryption - gateway = await ethers.getContractAt(gatewayArtifact.abi, GATEWAYCONTRACT_ADDRESS); - gateway.on( - "EventDecryption", - async (requestID, cts, contractCaller, callbackSelector, msgValue, maxTimestamp, eventData) => { - const blockNumber = eventData.log.blockNumber; - console.log(`${await currentTime()} - Requested decrypt on block ${blockNumber} (requestID ${requestID})`); - }, - ); - gateway.on("ResultCallback", async (requestID, success, result, eventData) => { - const blockNumber = eventData.log.blockNumber; - console.log(`${await currentTime()} - Fulfilled decrypt on block ${blockNumber} (requestID ${requestID})`); - }); -}; - -export const awaitAllDecryptionResults = async (): Promise => { - gateway = await ethers.getContractAt(gatewayArtifact.abi, GATEWAYCONTRACT_ADDRESS); - const provider = ethers.provider; - if (networkName === "hardhat" && hre.__SOLIDITY_COVERAGE_RUNNING !== true) { - // evm_snapshot is not supported in coverage mode - lastBlockSnapshotForDecrypt = await provider.send("get_lastBlockSnapshotForDecrypt"); - if (lastBlockSnapshotForDecrypt < firstBlockListening) { - firstBlockListening = lastBlockSnapshotForDecrypt + 1; - } - } - await fulfillAllPastRequestsIds(networkName === "hardhat"); - firstBlockListening = (await ethers.provider.getBlockNumber()) + 1; - if (networkName === "hardhat" && hre.__SOLIDITY_COVERAGE_RUNNING !== true) { - // evm_snapshot is not supported in coverage mode - await provider.send("set_lastBlockSnapshotForDecrypt", [firstBlockListening]); - } -}; - -const getAlreadyFulfilledDecryptions = async (): Promise => { - let results: bigint[] = []; - const eventDecryptionResult = await gateway.filters.ResultCallback().getTopicFilter(); - const filterDecryptionResult = { - address: GATEWAYCONTRACT_ADDRESS, - fromBlock: firstBlockListening, - toBlock: "latest", - topics: eventDecryptionResult, - }; - const pastResults = await ethers.provider.getLogs(filterDecryptionResult); - results = results.concat(pastResults.map((result) => ifaceResultCallback?.parseLog(result)?.args[0])); - return results; -}; - -const allTrue = (arr: boolean[], fn = Boolean) => arr.every(fn); - -const fulfillAllPastRequestsIds = async (mocked: boolean) => { - const eventDecryption = await gateway.filters.EventDecryption().getTopicFilter(); - const results = await getAlreadyFulfilledDecryptions(); - const filterDecryption = { - address: GATEWAYCONTRACT_ADDRESS, - fromBlock: firstBlockListening, - toBlock: "latest", - topics: eventDecryption, - }; - const pastRequests = await ethers.provider.getLogs(filterDecryption); - for (const request of pastRequests) { - const event = ifaceEventDecryption.parseLog(request); - const requestID = event?.args[0]; - const handles = event?.args[1]; - const typesList = handles.map((handle) => parseInt(handle.toString(16).slice(-4, -2), 16)); - const msgValue = event?.args[4]; - const passSignaturesToCaller = event?.args[6]; - if (!results.includes(requestID)) { - // if request is not already fulfilled - if (mocked) { - // in mocked mode, we trigger the decryption fulfillment manually - await awaitCoprocessor(); - - // first check tat all handles are allowed for decryption - const aclArtifact = await import("../node_modules/fhevm-core-contracts/artifacts/contracts/ACL.sol/ACL.json"); - const acl = await ethers.getContractAt(aclArtifact.abi, ACL_ADDRESS); - const isAllowedForDec = await Promise.all(handles.map(async (handle) => acl.isAllowedForDecryption(handle))); - if (!allTrue(isAllowedForDec)) { - throw new Error("Some handle is not authorized for decryption"); - } - const types = typesList.map((num: number) => CiphertextType[num]); - const values = await Promise.all(handles.map(async (handle) => BigInt(await getClearText(handle)))); - const valuesFormatted = values.map((value, index) => - types[index] === "address" ? "0x" + value.toString(16).padStart(40, "0") : value, - ); - const valuesFormatted2 = valuesFormatted.map((value, index) => - typesList[index] === 9 ? "0x" + value.toString(16).padStart(128, "0") : value, - ); - const valuesFormatted3 = valuesFormatted2.map((value, index) => - typesList[index] === 10 ? "0x" + value.toString(16).padStart(256, "0") : value, - ); - const valuesFormatted4 = valuesFormatted3.map((value, index) => - typesList[index] === 11 ? "0x" + value.toString(16).padStart(512, "0") : value, - ); - - const abiCoder = new ethers.AbiCoder(); - let encodedData; - let calldata; - if (!passSignaturesToCaller) { - encodedData = abiCoder.encode(["uint256", ...types], [31, ...valuesFormatted4]); // 31 is just a dummy uint256 requestID to get correct abi encoding for the remaining arguments (i.e everything except the requestID) - calldata = "0x" + encodedData.slice(66); // we just pop the dummy requestID to get the correct value to pass for `decryptedCts` - } else { - encodedData = abiCoder.encode(["uint256", ...types, "bytes[]"], [31, ...valuesFormatted4, []]); // adding also a dummy empty array of bytes for correct abi-encoding when used with signatures - calldata = "0x" + encodedData.slice(66).slice(0, -64); // we also pop the last 32 bytes (empty bytes[]) - } - - const numSigners = 1; // for the moment mocked mode only uses 1 signer - const decryptResultsEIP712signatures = await computeDecryptSignatures(handles, calldata, numSigners); - const relayer = await impersonateNullAddress(); - await gateway - .connect(relayer) - .fulfillRequest(requestID, calldata, decryptResultsEIP712signatures, { value: msgValue }); - } else { - // in non-mocked mode we must wait until the gateway service relayer submits the decryption fulfillment tx - await waitNBlocks(1); - await fulfillAllPastRequestsIds(mocked); - } - } - } -}; - -async function computeDecryptSignatures( - handlesList: bigint[], - decryptedResult: string, - numSigners: number, -): Promise { - const signatures: string[] = []; - - for (let idx = 0; idx < numSigners; idx++) { - const privKeySigner = PRIVATE_KEY_KMS_SIGNER; - if (privKeySigner) { - const kmsSigner = new ethers.Wallet(privKeySigner).connect(ethers.provider); - const signature = await kmsSign(handlesList, decryptedResult, kmsSigner); - signatures.push(signature); - } else { - throw new Error(`Private key for signer ${idx} not found in environment variables`); - } - } - return signatures; -} - -async function kmsSign(handlesList: bigint[], decryptedResult: string, kmsSigner: Wallet) { - const kmsAdd = KMSVERIFIER_ADDRESS; - const chainId = (await ethers.provider.getNetwork()).chainId; - - const domain = { - name: "KMSVerifier", - version: "1", - chainId: chainId, - verifyingContract: kmsAdd, - }; - - const types = { - DecryptionResult: [ - { - name: "aclAddress", - type: "address", - }, - { - name: "handlesList", - type: "uint256[]", - }, - { - name: "decryptedResult", - type: "bytes", - }, - ], - }; - const message = { - aclAddress: aclAdd, - handlesList: handlesList, - decryptedResult: decryptedResult, - }; - - const signature = await kmsSigner.signTypedData(domain, types, message); - const sigRSV = ethers.Signature.from(signature); - const v = 27 + sigRSV.yParity; - const r = sigRSV.r; - const s = sigRSV.s; - - const result = r + s.substring(2) + v.toString(16); - return result; -} diff --git a/contracts/test/confidentialCounter/sample1.ts b/contracts/test/confidentialCounter/sample1.ts deleted file mode 100644 index 8ffbeef..0000000 --- a/contracts/test/confidentialCounter/sample1.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { ethers } from "hardhat"; - -import { createInstance } from "../instance"; -import { getSigners, initSigners } from "../signers"; - -describe("EncryptedCounter1", function () { - before(async function () { - await initSigners(); // Initialize signers - this.signers = await getSigners(); - }); - - beforeEach(async function () { - const CounterFactory = await ethers.getContractFactory("EncryptedCounter1"); - this.counterContract = await CounterFactory.connect(this.signers.alice).deploy(); - await this.counterContract.waitForDeployment(); - this.contractAddress = await this.counterContract.getAddress(); - this.instances = await createInstance(); - }); - - it("should increment the counter", async function () { - // Perform the increment action - const tx = await this.counterContract.increment(); - await tx.wait(); - }); -}); diff --git a/contracts/test/confidentialCounter/sample2.ts b/contracts/test/confidentialCounter/sample2.ts deleted file mode 100644 index d64caa2..0000000 --- a/contracts/test/confidentialCounter/sample2.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { ethers } from "hardhat"; - -import { createInstance } from "../instance"; -import { getSigners, initSigners } from "../signers"; - -describe("EncryptedCounter2", function () { - before(async function () { - await initSigners(); // Initialize signers - this.signers = await getSigners(); - }); - - beforeEach(async function () { - const CounterFactory = await ethers.getContractFactory("EncryptedCounter2"); - this.counterContract = await CounterFactory.connect(this.signers.alice).deploy(); - await this.counterContract.waitForDeployment(); - this.contractAddress = await this.counterContract.getAddress(); - this.instances = await createInstance(); // Set up instances for testing - }); - - it("should increment by arbitrary encrypted amount", async function () { - // Create encrypted input for amount to increment by - const input = this.instances.createEncryptedInput(this.contractAddress, this.signers.alice.address); - input.add8(5); - const encryptedAmount = await input.encrypt(); - - // Call incrementBy with encrypted amount - const tx = await this.counterContract.incrementBy(encryptedAmount.handles[0], encryptedAmount.inputProof); - await tx.wait(); - }); -}); diff --git a/contracts/test/confidentialCounter/sample3.ts b/contracts/test/confidentialCounter/sample3.ts deleted file mode 100644 index 5793341..0000000 --- a/contracts/test/confidentialCounter/sample3.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { expect } from "chai"; -import { ethers } from "hardhat"; - -import { awaitAllDecryptionResults, initGateway } from "../asyncDecrypt"; -import { createInstance } from "../instance"; -import { getSigners, initSigners } from "../signers"; - -describe("EncryptedCounter3", function () { - before(async function () { - await initSigners(); // Initialize signers - this.signers = await getSigners(); - await initGateway(); // Initialize the gateway for decryption - }); - - beforeEach(async function () { - const CounterFactory = await ethers.getContractFactory("EncryptedCounter3"); - this.counterContract = await CounterFactory.connect(this.signers.alice).deploy(); - await this.counterContract.waitForDeployment(); - this.contractAddress = await this.counterContract.getAddress(); - this.instances = await createInstance(); // Set up instances for testing - }); - - it("should increment counter and decrypt the result", async function () { - // Create encrypted input for amount to increment by - const input = this.instances.createEncryptedInput(this.contractAddress, this.signers.alice.address); - input.add8(5); // Increment by 5 as an example - const encryptedAmount = await input.encrypt(); - - // Call incrementBy with encrypted amount - const tx = await this.counterContract.incrementBy(encryptedAmount.handles[0], encryptedAmount.inputProof); - await tx.wait(); - - const tx4 = await this.counterContract.connect(this.signers.carol).requestDecryptCounter(); - await tx4.wait(); - - // Wait for decryption to complete - await awaitAllDecryptionResults(); - - // Check decrypted value (should be 3: initial 0 + three increments) - const decryptedValue = await this.counterContract.getDecryptedCounter(); - expect(decryptedValue).to.equal(5); - }); -}); diff --git a/contracts/test/confidentialCounter/sample4.ts b/contracts/test/confidentialCounter/sample4.ts deleted file mode 100644 index fb252cb..0000000 --- a/contracts/test/confidentialCounter/sample4.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { expect } from "chai"; -import { ethers } from "hardhat"; - -import { createInstance } from "../instance"; -import { reencryptEuint8 } from "../reencrypt"; -import { getSigners, initSigners } from "../signers"; - -describe("EncryptedCounter4", function () { - before(async function () { - await initSigners(); // Initialize signers - this.signers = await getSigners(); - }); - - beforeEach(async function () { - const CounterFactory = await ethers.getContractFactory("EncryptedCounter4"); - this.counterContract = await CounterFactory.connect(this.signers.alice).deploy(); - await this.counterContract.waitForDeployment(); - this.contractAddress = await this.counterContract.getAddress(); - this.instances = await createInstance(); - }); - - it("should allow reencryption and decryption of counter value", async function () { - const input = this.instances.createEncryptedInput(this.contractAddress, this.signers.alice.address); - input.add8(1); // Increment by 1 as an example - const encryptedAmount = await input.encrypt(); - - // Call incrementBy with encrypted amount - const tx = await this.counterContract.incrementBy(encryptedAmount.handles[0], encryptedAmount.inputProof); - await tx.wait(); - - // Get the encrypted counter value - const encryptedCounter = await this.counterContract.getCounter(); - - const decryptedValue = await reencryptEuint8( - this.signers, - this.instances, - "alice", - encryptedCounter, - this.contractAddress, - ); - - // Verify the decrypted value is 1 (since we incremented once) - expect(decryptedValue).to.equal(1); - }); - - it("should allow reencryption of counter value", async function () { - const input = this.instances.createEncryptedInput(this.contractAddress, this.signers.bob.address); - input.add8(1); // Increment by 1 as an example - const encryptedAmount = await input.encrypt(); - - // Call incrementBy with encrypted amount - const tx = await this.counterContract - .connect(this.signers.bob) - .incrementBy(encryptedAmount.handles[0], encryptedAmount.inputProof); - await tx.wait(); - - // Get the encrypted counter value - const encryptedCounter = await this.counterContract.connect(this.signers.bob).getCounter(); - - const decryptedValue = await reencryptEuint8( - this.signers, - this.instances, - "bob", - encryptedCounter, - this.contractAddress, - ); - - // Verify the decrypted value is 1 (since we incremented once) - expect(decryptedValue).to.equal(1); - }); -}); diff --git a/contracts/test/confidentialERC20/ConfidentialERC20.FHEGas.ts b/contracts/test/confidentialERC20/ConfidentialERC20.FHEGas.ts deleted file mode 100644 index a80f10a..0000000 --- a/contracts/test/confidentialERC20/ConfidentialERC20.FHEGas.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { expect } from "chai"; - -import { getFHEGasFromTxReceipt } from "../coprocessorUtils"; -import { createInstance } from "../instance"; -import { getSigners, initSigners } from "../signers"; -import { deployConfidentialERC20Fixture } from "./ConfidentialERC20.fixture"; - -describe("ConfidentialERC20:FHEGas", function () { - before(async function () { - await initSigners(); - this.signers = await getSigners(); - }); - - beforeEach(async function () { - const contract = await deployConfidentialERC20Fixture(); - this.contractAddress = await contract.getAddress(); - this.erc20 = contract; - this.fhevm = await createInstance(); - }); - - it("gas consumed during transfer", async function () { - const transaction = await this.erc20.mint(10000); - const t1 = await transaction.wait(); - expect(t1?.status).to.eq(1); - - const input = this.fhevm.createEncryptedInput(this.contractAddress, this.signers.alice.address); - input.add64(1337); - const encryptedTransferAmount = await input.encrypt(); - const tx = await this.erc20["transfer(address,bytes32,bytes)"]( - this.signers.bob.address, - encryptedTransferAmount.handles[0], - encryptedTransferAmount.inputProof, - ); - const t2 = await tx.wait(); - expect(t2?.status).to.eq(1); - const FHEGasConsumedTransfer = getFHEGasFromTxReceipt(t2); - console.log("FHEGas Consumed during transfer", FHEGasConsumedTransfer); - // contrarily to FHEGas, native gas in mocked mode slightly differs from the real gas consumption on fhevm (underestimated by ~20%) - console.log("Native Gas Consumed during transfer", t2.gasUsed); - }); - - it("gas consumed during transferFrom", async function () { - const transaction = await this.erc20.mint(10000); - await transaction.wait(); - - const inputAlice = this.fhevm.createEncryptedInput(this.contractAddress, this.signers.alice.address); - inputAlice.add64(1337); - const encryptedAllowanceAmount = await inputAlice.encrypt(); - const tx = await this.erc20["approve(address,bytes32,bytes)"]( - this.signers.bob.address, - encryptedAllowanceAmount.handles[0], - encryptedAllowanceAmount.inputProof, - ); - await tx.wait(); - - const bobErc20 = this.erc20.connect(this.signers.bob); - const inputBob2 = this.fhevm.createEncryptedInput(this.contractAddress, this.signers.bob.address); - inputBob2.add64(1337); // below allowance so next tx should send token - const encryptedTransferAmount2 = await inputBob2.encrypt(); - const tx3 = await bobErc20["transferFrom(address,address,bytes32,bytes)"]( - this.signers.alice.address, - this.signers.bob.address, - encryptedTransferAmount2.handles[0], - encryptedTransferAmount2.inputProof, - ); - const t3 = await tx3.wait(); - const FHEGasConsumedTransferFrom = getFHEGasFromTxReceipt(t3); - console.log("FHEGas Consumed during transferFrom", FHEGasConsumedTransferFrom); - // contrarily to FHEGas, native gas in mocked mode slightly differs from the real gas consumption on fhevm (underestimated by ~20%) - console.log("Native Gas Consumed during transfer", t3.gasUsed); - }); -}); diff --git a/contracts/test/confidentialERC20/ConfidentialERC20.fixture.ts b/contracts/test/confidentialERC20/ConfidentialERC20.fixture.ts deleted file mode 100644 index 78881ff..0000000 --- a/contracts/test/confidentialERC20/ConfidentialERC20.fixture.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { ethers } from "hardhat"; - -import type { MyConfidentialERC20 } from "../../types"; -import { getSigners } from "../signers"; - -export async function deployConfidentialERC20Fixture(): Promise { - const signers = await getSigners(); - - const contractFactory = await ethers.getContractFactory("MyConfidentialERC20"); - const contract = await contractFactory.connect(signers.alice).deploy("Naraggara", "NARA"); // City of Zama's battle - await contract.waitForDeployment(); - - return contract; -} diff --git a/contracts/test/confidentialERC20/ConfidentialERC20.ts b/contracts/test/confidentialERC20/ConfidentialERC20.ts deleted file mode 100644 index e892ea9..0000000 --- a/contracts/test/confidentialERC20/ConfidentialERC20.ts +++ /dev/null @@ -1,218 +0,0 @@ -import { expect } from "chai"; -import { network } from "hardhat"; - -import { createInstance } from "../instance"; -import { reencryptEuint64 } from "../reencrypt"; -import { getSigners, initSigners } from "../signers"; -import { debug } from "../utils"; -import { deployConfidentialERC20Fixture } from "./ConfidentialERC20.fixture"; - -describe("ConfidentialERC20", function () { - before(async function () { - await initSigners(); - this.signers = await getSigners(); - }); - - beforeEach(async function () { - const contract = await deployConfidentialERC20Fixture(); - this.contractAddress = await contract.getAddress(); - this.erc20 = contract; - this.fhevm = await createInstance(); - }); - - it("should mint the contract", async function () { - const transaction = await this.erc20.mint(1000); - await transaction.wait(); - - // Reencrypt Alice's balance - const balanceHandleAlice = await this.erc20.balanceOf(this.signers.alice); - const balanceAlice = await reencryptEuint64( - this.signers, - this.fhevm, - "alice", - balanceHandleAlice, - this.contractAddress, - ); - - expect(balanceAlice).to.equal(1000); - - const totalSupply = await this.erc20.totalSupply(); - expect(totalSupply).to.equal(1000); - }); - - it("should transfer tokens between two users", async function () { - const transaction = await this.erc20.mint(10000); - const t1 = await transaction.wait(); - expect(t1?.status).to.eq(1); - - const input = this.fhevm.createEncryptedInput(this.contractAddress, this.signers.alice.address); - input.add64(1337); - const encryptedTransferAmount = await input.encrypt(); - const tx = await this.erc20["transfer(address,bytes32,bytes)"]( - this.signers.bob.address, - encryptedTransferAmount.handles[0], - encryptedTransferAmount.inputProof, - ); - const t2 = await tx.wait(); - expect(t2?.status).to.eq(1); - - // Reencrypt Alice's balance - const balanceHandleAlice = await this.erc20.balanceOf(this.signers.alice); - const balanceAlice = await reencryptEuint64( - this.signers, - this.fhevm, - "alice", - balanceHandleAlice, - this.contractAddress, - ); - expect(balanceAlice).to.equal(10000 - 1337); - - // Reencrypt Bob's balance - const balanceHandleBob = await this.erc20.balanceOf(this.signers.bob); - const balanceBob = await reencryptEuint64(this.signers, this.fhevm, "bob", balanceHandleBob, this.contractAddress); - expect(balanceBob).to.equal(1337); - - // on the other hand, Bob should be unable to read Alice's balance - await expect( - reencryptEuint64(this.signers, this.fhevm, "bob", balanceHandleAlice, this.contractAddress), - ).to.be.rejectedWith("User is not authorized to reencrypt this handle!"); - - // and should be impossible to call reencrypt if contractAddress === userAddress - await expect( - reencryptEuint64(this.signers, this.fhevm, "alice", balanceHandleAlice, this.signers.alice.address), - ).to.be.rejectedWith("userAddress should not be equal to contractAddress when requesting reencryption!"); - }); - - it("should not transfer tokens between two users", async function () { - const transaction = await this.erc20.mint(1000); - await transaction.wait(); - - const input = this.fhevm.createEncryptedInput(this.contractAddress, this.signers.alice.address); - input.add64(1337); - const encryptedTransferAmount = await input.encrypt(); - const tx = await this.erc20["transfer(address,bytes32,bytes)"]( - this.signers.bob.address, - encryptedTransferAmount.handles[0], - encryptedTransferAmount.inputProof, - ); - await tx.wait(); - - const balanceHandleAlice = await this.erc20.balanceOf(this.signers.alice); - const balanceAlice = await reencryptEuint64( - this.signers, - this.fhevm, - "alice", - balanceHandleAlice, - this.contractAddress, - ); - expect(balanceAlice).to.equal(1000); - - // Reencrypt Bob's balance - const balanceHandleBob = await this.erc20.balanceOf(this.signers.bob); - const balanceBob = await reencryptEuint64(this.signers, this.fhevm, "bob", balanceHandleBob, this.contractAddress); - expect(balanceBob).to.equal(0); - }); - - it("should be able to transferFrom only if allowance is sufficient", async function () { - const transaction = await this.erc20.mint(10000); - await transaction.wait(); - - const inputAlice = this.fhevm.createEncryptedInput(this.contractAddress, this.signers.alice.address); - inputAlice.add64(1337); - const encryptedAllowanceAmount = await inputAlice.encrypt(); - const tx = await this.erc20["approve(address,bytes32,bytes)"]( - this.signers.bob.address, - encryptedAllowanceAmount.handles[0], - encryptedAllowanceAmount.inputProof, - ); - await tx.wait(); - - const bobErc20 = this.erc20.connect(this.signers.bob); - const inputBob1 = this.fhevm.createEncryptedInput(this.contractAddress, this.signers.bob.address); - inputBob1.add64(1338); // above allowance so next tx should actually not send any token - const encryptedTransferAmount = await inputBob1.encrypt(); - const tx2 = await bobErc20["transferFrom(address,address,bytes32,bytes)"]( - this.signers.alice.address, - this.signers.bob.address, - encryptedTransferAmount.handles[0], - encryptedTransferAmount.inputProof, - ); - await tx2.wait(); - - // Decrypt Alice's balance - const balanceHandleAlice = await this.erc20.balanceOf(this.signers.alice); - const balanceAlice = await reencryptEuint64( - this.signers, - this.fhevm, - "alice", - balanceHandleAlice, - this.contractAddress, - ); - expect(balanceAlice).to.equal(10000); // check that transfer did not happen, as expected - - // Decrypt Bob's balance - const balanceHandleBob = await this.erc20.balanceOf(this.signers.bob); - const balanceBob = await reencryptEuint64(this.signers, this.fhevm, "bob", balanceHandleBob, this.contractAddress); - expect(balanceBob).to.equal(0); // check that transfer did not happen, as expected - - const inputBob2 = this.fhevm.createEncryptedInput(this.contractAddress, this.signers.bob.address); - inputBob2.add64(1337); // below allowance so next tx should send token - const encryptedTransferAmount2 = await inputBob2.encrypt(); - const tx3 = await bobErc20["transferFrom(address,address,bytes32,bytes)"]( - this.signers.alice.address, - this.signers.bob.address, - encryptedTransferAmount2.handles[0], - encryptedTransferAmount2.inputProof, - ); - await tx3.wait(); - - // Decrypt Alice's balance - const balanceHandleAlice2 = await this.erc20.balanceOf(this.signers.alice); - const balanceAlice2 = await reencryptEuint64( - this.signers, - this.fhevm, - "alice", - balanceHandleAlice2, - this.contractAddress, - ); - expect(balanceAlice2).to.equal(10000 - 1337); // check that transfer did happen this time - - // Decrypt Bob's balance - const balanceHandleBob2 = await this.erc20.balanceOf(this.signers.bob); - const balanceBob2 = await reencryptEuint64( - this.signers, - this.fhevm, - "bob", - balanceHandleBob2, - this.contractAddress, - ); - expect(balanceBob2).to.equal(1337); // check that transfer did happen this time - }); - - it("DEBUG - using debug.decrypt64 for debugging transfer", async function () { - if (network.name === "hardhat") { - // using the debug.decryptXX functions is possible only in mocked mode - - const transaction = await this.erc20.mint(1000); - await transaction.wait(); - const input = this.fhevm.createEncryptedInput(this.contractAddress, this.signers.alice.address); - input.add64(1337); - const encryptedTransferAmount = await input.encrypt(); - const tx = await this.erc20["transfer(address,bytes32,bytes)"]( - this.signers.bob.address, - encryptedTransferAmount.handles[0], - encryptedTransferAmount.inputProof, - ); - await tx.wait(); - - const balanceHandleAlice = await this.erc20.balanceOf(this.signers.alice); - const balanceAlice = await debug.decrypt64(balanceHandleAlice); - expect(balanceAlice).to.equal(1000); - - // Reencrypt Bob's balance - const balanceHandleBob = await this.erc20.balanceOf(this.signers.bob); - const balanceBob = await debug.decrypt64(balanceHandleBob); - expect(balanceBob).to.equal(0); - } - }); -}); diff --git a/contracts/test/constants.ts b/contracts/test/constants.ts deleted file mode 100644 index 7c9d80e..0000000 --- a/contracts/test/constants.ts +++ /dev/null @@ -1,10 +0,0 @@ -export const TFHEEXECUTOR_ADDRESS = "0x687408ab54661ba0b4aef3a44156c616c6955e07"; -export const ACL_ADDRESS = "0xfee8407e2f5e3ee68ad77cae98c434e637f516e5"; -export const FHEPAYMENT_ADDRESS = "0xfb03be574d14c256d56f09a198b586bdfc0a9de2"; -export const KMSVERIFIER_ADDRESS = "0x9d6891a6240d6130c54ae243d8005063d05fe14b"; -export const INPUTVERIFIER_ADDRESS = "0x3a2DA6f1daE9eF988B48d9CF27523FA31a8eBE50"; -export const GATEWAYCONTRACT_ADDRESS = "0x33347831500f1e73f0cccbb95c9f86b94d7b1123"; -export const PRIVATE_KEY_KMS_SIGNER = "388b7680e4e1afa06efbfd45cdd1fe39f3c6af381df6555a19661f283b97de91"; -export const PRIVATE_KEY_COPROCESSOR_ACCOUNT = "7ec8ada6642fc4ccfb7729bc29c17cf8d21b61abd5642d1db992c0b8672ab901"; -export const GATEWAY_URL = "https://gateway.sepolia.zama.ai/"; -export const ACCOUNT_NAMES = ["alice", "bob", "carol", "dave", "eve", "fred", "greg", "hugo", "ian", "jane"]; diff --git a/contracts/test/coprocessorUtils.ts b/contracts/test/coprocessorUtils.ts deleted file mode 100644 index f21ac8e..0000000 --- a/contracts/test/coprocessorUtils.ts +++ /dev/null @@ -1,901 +0,0 @@ -import { log2 } from "extra-bigint"; -import { ethers } from "hardhat"; -import hre from "hardhat"; -import { Database } from "sqlite3"; - -import { TFHEEXECUTOR_ADDRESS } from "./constants"; -import operatorsPrices from "./operatorsPrices.json"; - -const executorAddress = TFHEEXECUTOR_ADDRESS; - -let firstBlockListening = 0; -let lastBlockSnapshot = 0; -let lastCounterRand = 0; -let counterRand = 0; - -//const db = new Database('./sql.db'); // on-disk db for debugging -const db = new Database(":memory:"); - -export function insertSQL(handle: string, clearText: bigint, replace: boolean = false) { - if (replace) { - // this is useful if using snapshots while sampling different random numbers on each revert - db.run("INSERT OR REPLACE INTO ciphertexts (handle, clearText) VALUES (?, ?)", [handle, clearText.toString()]); - } else { - db.run("INSERT OR IGNORE INTO ciphertexts (handle, clearText) VALUES (?, ?)", [handle, clearText.toString()]); - } -} - -// Decrypt any handle, bypassing ACL -// WARNING : only for testing or internal use -export const getClearText = async (handle: bigint): Promise => { - const handleStr = "0x" + handle.toString(16).padStart(64, "0"); - - return new Promise((resolve, reject) => { - let attempts = 0; - const maxRetries = 100; - - function executeQuery() { - db.get("SELECT clearText FROM ciphertexts WHERE handle = ?", [handleStr], (err, row) => { - if (err) { - reject(new Error(`Error querying database: ${err.message}`)); - } else if (row) { - resolve(row.clearText); - } else if (attempts < maxRetries) { - attempts++; - executeQuery(); - } else { - reject(new Error("No record found after maximum retries")); - } - }); - } - - executeQuery(); - }); -}; - -db.serialize(() => db.run("CREATE TABLE IF NOT EXISTS ciphertexts (handle BINARY PRIMARY KEY,clearText TEXT)")); - -interface FHEVMEvent { - eventName: string; - args: object; -} - -const NumBits = { - 0: 1n, //ebool - 1: 4n, //euint4 - 2: 8n, //euint8 - 3: 16n, //euint16 - 4: 32n, //euint32 - 5: 64n, //euint64 - 6: 128n, //euint128 - 7: 160n, //eaddress - 8: 256n, //euint256 - 9: 512n, //ebytes64 - 10: 1024n, //ebytes128 - 11: 2048n, //ebytes256 -}; - -export function numberToEvenHexString(num: number) { - if (typeof num !== "number" || num < 0) { - throw new Error("Input should be a non-negative number."); - } - let hexString = num.toString(16); - if (hexString.length % 2 !== 0) { - hexString = "0" + hexString; - } - return hexString; -} - -function getRandomBigInt(numBits: number): bigint { - if (numBits <= 0) { - throw new Error("Number of bits must be greater than 0"); - } - const numBytes = Math.ceil(numBits / 8); - const randomBytes = new Uint8Array(numBytes); - crypto.getRandomValues(randomBytes); - let randomBigInt = BigInt(0); - for (let i = 0; i < numBytes; i++) { - randomBigInt = (randomBigInt << BigInt(8)) | BigInt(randomBytes[i]); - } - const mask = (BigInt(1) << BigInt(numBits)) - BigInt(1); - randomBigInt = randomBigInt & mask; - return randomBigInt; -} - -function bitwiseNotUintBits(value: bigint, numBits: number) { - if (typeof value !== "bigint") { - throw new TypeError("The input value must be a BigInt."); - } - if (typeof numBits !== "number" || numBits <= 0) { - throw new TypeError("The numBits parameter must be a positive integer."); - } - // Create the mask with numBits bits set to 1 - const BIT_MASK = (BigInt(1) << BigInt(numBits)) - BigInt(1); - return ~value & BIT_MASK; -} - -export const awaitCoprocessor = async (): Promise => { - await processAllPastTFHEExecutorEvents(); -}; - -const abi = [ - "event FheAdd(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", - "event FheSub(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", - "event FheMul(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", - "event FheDiv(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", - "event FheRem(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", - "event FheBitAnd(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", - "event FheBitOr(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", - "event FheBitXor(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", - "event FheShl(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", - "event FheShr(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", - "event FheRotl(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", - "event FheRotr(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", - "event FheEq(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", - "event FheEqBytes(uint256 lhs, bytes rhs, bytes1 scalarByte, uint256 result)", - "event FheNe(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", - "event FheNeBytes(uint256 lhs, bytes rhs, bytes1 scalarByte, uint256 result)", - "event FheGe(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", - "event FheGt(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", - "event FheLe(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", - "event FheLt(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", - "event FheMin(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", - "event FheMax(uint256 lhs, uint256 rhs, bytes1 scalarByte, uint256 result)", - "event FheNeg(uint256 ct, uint256 result)", - "event FheNot(uint256 ct, uint256 result)", - "event VerifyCiphertext(bytes32 inputHandle,address userAddress,bytes inputProof,bytes1 inputType,uint256 result)", - "event Cast(uint256 ct, bytes1 toType, uint256 result)", - "event TrivialEncrypt(uint256 pt, bytes1 toType, uint256 result)", - "event TrivialEncryptBytes(bytes pt, bytes1 toType, uint256 result)", - "event FheIfThenElse(uint256 control, uint256 ifTrue, uint256 ifFalse, uint256 result)", - "event FheRand(bytes1 randType, uint256 result)", - "event FheRandBounded(uint256 upperBound, bytes1 randType, uint256 result)", -]; - -async function processAllPastTFHEExecutorEvents() { - const provider = ethers.provider; - const latestBlockNumber = await provider.getBlockNumber(); - - if (hre.__SOLIDITY_COVERAGE_RUNNING !== true) { - // evm_snapshot is not supported in coverage mode - [lastBlockSnapshot, lastCounterRand] = await provider.send("get_lastBlockSnapshot"); - if (lastBlockSnapshot < firstBlockListening) { - firstBlockListening = lastBlockSnapshot + 1; - counterRand = Number(lastCounterRand); - } - } - - const contract = new ethers.Contract(executorAddress, abi, provider); - - // Fetch all events emitted by the contract - const filter = { - address: executorAddress, - fromBlock: firstBlockListening, - toBlock: latestBlockNumber, - }; - - const logs = await provider.getLogs(filter); - - const events = logs - .map((log) => { - try { - const parsedLog = contract.interface.parseLog(log); - return { - eventName: parsedLog.name, - args: parsedLog.args, - }; - } catch (e) { - // If the log cannot be parsed, skip it - return null; - } - }) - .filter((event) => event !== null); - - firstBlockListening = latestBlockNumber + 1; - if (hre.__SOLIDITY_COVERAGE_RUNNING !== true) { - // evm_snapshot is not supported in coverage mode - await provider.send("set_lastBlockSnapshot", [firstBlockListening]); - } - events.map(async (event) => await insertHandleFromEvent(event)); -} - -async function insertHandleFromEvent(event: FHEVMEvent) { - let handle; - let clearText; - let clearLHS; - let clearRHS; - let resultType; - let shift; - - switch (event.eventName) { - case "TrivialEncrypt": - clearText = event.args[0]; - handle = ethers.toBeHex(event.args[2], 32); - insertSQL(handle, clearText); - break; - - case "TrivialEncryptBytes": - clearText = event.args[0]; - handle = ethers.toBeHex(event.args[2], 32); - insertSQL(handle, clearText); - break; - - case "FheAdd": - handle = ethers.toBeHex(event.args[3], 32); - resultType = parseInt(handle.slice(-4, -2), 16); - clearLHS = await getClearText(event.args[0]); - if (event.args[2] === "0x01") { - clearText = BigInt(clearLHS) + event.args[1]; - clearText = clearText % 2n ** NumBits[resultType]; - } else { - clearRHS = await getClearText(event.args[1]); - clearText = BigInt(clearLHS) + BigInt(clearRHS); - clearText = clearText % 2n ** NumBits[resultType]; - } - insertSQL(ethers.toBeHex(handle, 32), clearText); - break; - - case "FheSub": - handle = ethers.toBeHex(event.args[3], 32); - resultType = parseInt(handle.slice(-4, -2), 16); - clearLHS = await getClearText(event.args[0]); - if (event.args[2] === "0x01") { - clearText = BigInt(clearLHS) - event.args[1]; - if (clearText < 0n) clearText = clearText + 2n ** NumBits[resultType]; - clearText = clearText % 2n ** NumBits[resultType]; - } else { - clearRHS = await getClearText(event.args[1]); - clearText = BigInt(clearLHS) - BigInt(clearRHS); - if (clearText < 0n) clearText = clearText + 2n ** NumBits[resultType]; - clearText = clearText % 2n ** NumBits[resultType]; - } - insertSQL(handle, clearText); - break; - - case "FheMul": - handle = ethers.toBeHex(event.args[3], 32); - resultType = parseInt(handle.slice(-4, -2), 16); - clearLHS = await getClearText(event.args[0]); - if (event.args[2] === "0x01") { - clearText = BigInt(clearLHS) * event.args[1]; - clearText = clearText % 2n ** NumBits[resultType]; - } else { - clearRHS = await getClearText(event.args[1]); - clearText = BigInt(clearLHS) * BigInt(clearRHS); - clearText = clearText % 2n ** NumBits[resultType]; - } - insertSQL(handle, clearText); - break; - - case "FheDiv": - handle = ethers.toBeHex(event.args[3], 32); - resultType = parseInt(handle.slice(-4, -2), 16); - clearLHS = await getClearText(event.args[0]); - if (event.args[2] === "0x01") { - clearText = BigInt(clearLHS) / event.args[1]; - } else { - throw new Error("Non-scalar div not implemented yet"); - } - insertSQL(handle, clearText); - break; - - case "FheRem": - handle = ethers.toBeHex(event.args[3], 32); - resultType = parseInt(handle.slice(-4, -2), 16); - clearLHS = await getClearText(event.args[0]); - if (event.args[2] === "0x01") { - clearText = BigInt(clearLHS) % event.args[1]; - } else { - throw new Error("Non-scalar rem not implemented yet"); - } - insertSQL(handle, clearText); - break; - - case "FheBitAnd": - handle = ethers.toBeHex(event.args[3], 32); - resultType = parseInt(handle.slice(-4, -2), 16); - clearLHS = await getClearText(event.args[0]); - if (event.args[2] === "0x01") { - clearText = BigInt(clearLHS) & event.args[1]; - clearText = clearText % 2n ** NumBits[resultType]; - } else { - clearRHS = await getClearText(event.args[1]); - clearText = BigInt(clearLHS) & BigInt(clearRHS); - clearText = clearText % 2n ** NumBits[resultType]; - } - insertSQL(handle, clearText); - break; - - case "FheBitOr": - handle = ethers.toBeHex(event.args[3], 32); - resultType = parseInt(handle.slice(-4, -2), 16); - clearLHS = await getClearText(event.args[0]); - if (event.args[2] === "0x01") { - clearText = BigInt(clearLHS) | event.args[1]; - clearText = clearText % 2n ** NumBits[resultType]; - } else { - clearRHS = await getClearText(event.args[1]); - clearText = BigInt(clearLHS) | BigInt(clearRHS); - clearText = clearText % 2n ** NumBits[resultType]; - } - insertSQL(handle, clearText); - break; - - case "FheBitXor": - handle = ethers.toBeHex(event.args[3], 32); - resultType = parseInt(handle.slice(-4, -2), 16); - clearLHS = await getClearText(event.args[0]); - if (event.args[2] === "0x01") { - clearText = BigInt(clearLHS) ^ event.args[1]; - clearText = clearText % 2n ** NumBits[resultType]; - } else { - clearRHS = await getClearText(event.args[1]); - clearText = BigInt(clearLHS) ^ BigInt(clearRHS); - clearText = clearText % 2n ** NumBits[resultType]; - } - insertSQL(handle, clearText); - break; - - case "FheShl": - handle = ethers.toBeHex(event.args[3], 32); - resultType = parseInt(handle.slice(-4, -2), 16); - clearLHS = await getClearText(event.args[0]); - if (event.args[2] === "0x01") { - clearText = BigInt(clearLHS) << event.args[1] % NumBits[resultType]; - clearText = clearText % 2n ** NumBits[resultType]; - } else { - clearRHS = await getClearText(event.args[1]); - clearText = BigInt(clearLHS) << BigInt(clearRHS) % NumBits[resultType]; - clearText = clearText % 2n ** NumBits[resultType]; - } - insertSQL(handle, clearText); - break; - - case "FheShr": - handle = ethers.toBeHex(event.args[3], 32); - resultType = parseInt(handle.slice(-4, -2), 16); - clearLHS = await getClearText(event.args[0]); - if (event.args[2] === "0x01") { - clearText = BigInt(clearLHS) >> event.args[1] % NumBits[resultType]; - clearText = clearText % 2n ** NumBits[resultType]; - } else { - clearRHS = await getClearText(event.args[1]); - clearText = BigInt(clearLHS) >> BigInt(clearRHS) % NumBits[resultType]; - clearText = clearText % 2n ** NumBits[resultType]; - } - insertSQL(handle, clearText); - break; - - case "FheRotl": - handle = ethers.toBeHex(event.args[3], 32); - resultType = parseInt(handle.slice(-4, -2), 16); - clearLHS = await getClearText(event.args[0]); - if (event.args[2] === "0x01") { - shift = event.args[1] % NumBits[resultType]; - clearText = (BigInt(clearLHS) << shift) | (BigInt(clearLHS) >> (NumBits[resultType] - shift)); - clearText = clearText % 2n ** NumBits[resultType]; - } else { - clearRHS = await getClearText(event.args[1]); - shift = BigInt(clearRHS) % NumBits[resultType]; - clearText = (BigInt(clearLHS) << shift) | (BigInt(clearLHS) >> (NumBits[resultType] - shift)); - clearText = clearText % 2n ** NumBits[resultType]; - } - insertSQL(handle, clearText); - break; - - case "FheRotr": - handle = ethers.toBeHex(event.args[3], 32); - resultType = parseInt(handle.slice(-4, -2), 16); - clearLHS = await getClearText(event.args[0]); - if (event.args[2] === "0x01") { - shift = event.args[1] % NumBits[resultType]; - clearText = (BigInt(clearLHS) >> shift) | (BigInt(clearLHS) << (NumBits[resultType] - shift)); - clearText = clearText % 2n ** NumBits[resultType]; - } else { - clearRHS = await getClearText(event.args[1]); - shift = BigInt(clearRHS) % NumBits[resultType]; - clearText = (BigInt(clearLHS) >> shift) | (BigInt(clearLHS) << (NumBits[resultType] - shift)); - clearText = clearText % 2n ** NumBits[resultType]; - } - insertSQL(handle, clearText); - break; - - case "FheEq": - handle = ethers.toBeHex(event.args[3], 32); - resultType = parseInt(handle.slice(-4, -2), 16); - clearLHS = await getClearText(event.args[0]); - if (event.args[2] === "0x01") { - clearText = BigInt(clearLHS) === event.args[1] ? 1n : 0n; - } else { - clearRHS = await getClearText(event.args[1]); - clearText = BigInt(clearLHS) === BigInt(clearRHS) ? 1n : 0n; - } - insertSQL(handle, clearText); - break; - - case "FheEqBytes": - handle = ethers.toBeHex(event.args[3], 32); - resultType = parseInt(handle.slice(-4, -2), 16); - clearLHS = await getClearText(event.args[0]); - if (event.args[2] === "0x01") { - clearText = BigInt(clearLHS) === BigInt(event.args[1]) ? 1n : 0n; - } else { - clearRHS = await getClearText(event.args[1]); - clearText = BigInt(clearLHS) === BigInt(clearRHS) ? 1n : 0n; - } - insertSQL(handle, clearText); - break; - - case "FheNe": - handle = ethers.toBeHex(event.args[3], 32); - resultType = parseInt(handle.slice(-4, -2), 16); - clearLHS = await getClearText(event.args[0]); - if (event.args[2] === "0x01") { - clearText = BigInt(clearLHS) !== event.args[1] ? 1n : 0n; - } else { - clearRHS = await getClearText(event.args[1]); - clearText = BigInt(clearLHS) !== BigInt(clearRHS) ? 1n : 0n; - } - insertSQL(handle, clearText); - break; - - case "FheNeBytes": - handle = ethers.toBeHex(event.args[3], 32); - resultType = parseInt(handle.slice(-4, -2), 16); - clearLHS = await getClearText(event.args[0]); - if (event.args[2] === "0x01") { - clearText = BigInt(clearLHS) !== BigInt(event.args[1]) ? 1n : 0n; - } else { - clearRHS = await getClearText(event.args[1]); - clearText = BigInt(clearLHS) !== BigInt(clearRHS) ? 1n : 0n; - } - insertSQL(handle, clearText); - break; - - case "FheGe": - handle = ethers.toBeHex(event.args[3], 32); - resultType = parseInt(handle.slice(-4, -2), 16); - clearLHS = await getClearText(event.args[0]); - if (event.args[2] === "0x01") { - clearText = BigInt(clearLHS) >= event.args[1] ? 1n : 0n; - } else { - clearRHS = await getClearText(event.args[1]); - clearText = BigInt(clearLHS) >= BigInt(clearRHS) ? 1n : 0n; - } - insertSQL(handle, clearText); - break; - - case "FheGt": - handle = ethers.toBeHex(event.args[3], 32); - resultType = parseInt(handle.slice(-4, -2), 16); - clearLHS = await getClearText(event.args[0]); - if (event.args[2] === "0x01") { - clearText = BigInt(clearLHS) > event.args[1] ? 1n : 0n; - } else { - clearRHS = await getClearText(event.args[1]); - clearText = BigInt(clearLHS) > BigInt(clearRHS) ? 1n : 0n; - } - insertSQL(handle, clearText); - break; - - case "FheLe": - handle = ethers.toBeHex(event.args[3], 32); - resultType = parseInt(handle.slice(-4, -2), 16); - clearLHS = await getClearText(event.args[0]); - if (event.args[2] === "0x01") { - clearText = BigInt(clearLHS) <= event.args[1] ? 1n : 0n; - } else { - clearRHS = await getClearText(event.args[1]); - clearText = BigInt(clearLHS) <= BigInt(clearRHS) ? 1n : 0n; - } - insertSQL(handle, clearText); - break; - - case "FheLt": - handle = ethers.toBeHex(event.args[3], 32); - resultType = parseInt(handle.slice(-4, -2), 16); - clearLHS = await getClearText(event.args[0]); - if (event.args[2] === "0x01") { - clearText = BigInt(clearLHS) < event.args[1] ? 1n : 0n; - } else { - clearRHS = await getClearText(event.args[1]); - clearText = BigInt(clearLHS) < BigInt(clearRHS) ? 1n : 0n; - } - insertSQL(handle, clearText); - break; - - case "FheMax": - handle = ethers.toBeHex(event.args[3], 32); - resultType = parseInt(handle.slice(-4, -2), 16); - clearLHS = await getClearText(event.args[0]); - if (event.args[2] === "0x01") { - clearText = BigInt(clearLHS) > event.args[1] ? clearLHS : event.args[1]; - } else { - clearRHS = await getClearText(event.args[1]); - clearText = BigInt(clearLHS) > BigInt(clearRHS) ? clearLHS : clearRHS; - } - insertSQL(handle, clearText); - break; - - case "FheMin": - handle = ethers.toBeHex(event.args[3], 32); - resultType = parseInt(handle.slice(-4, -2), 16); - clearLHS = await getClearText(event.args[0]); - if (event.args[2] === "0x01") { - clearText = BigInt(clearLHS) < event.args[1] ? clearLHS : event.args[1]; - } else { - clearRHS = await getClearText(event.args[1]); - clearText = BigInt(clearLHS) < BigInt(clearRHS) ? clearLHS : clearRHS; - } - insertSQL(handle, clearText); - break; - - case "Cast": - resultType = parseInt(event.args[1]); - handle = ethers.toBeHex(event.args[2], 32); - clearText = BigInt(await getClearText(event.args[0])) % 2n ** NumBits[resultType]; - insertSQL(handle, clearText); - break; - - case "FheNot": - handle = ethers.toBeHex(event.args[1], 32); - resultType = parseInt(handle.slice(-4, -2), 16); - clearText = BigInt(await getClearText(event.args[0])); - clearText = bitwiseNotUintBits(clearText, Number(NumBits[resultType])); - insertSQL(handle, clearText); - break; - - case "FheNeg": - handle = ethers.toBeHex(event.args[1], 32); - resultType = parseInt(handle.slice(-4, -2), 16); - clearText = BigInt(await getClearText(event.args[0])); - clearText = bitwiseNotUintBits(clearText, Number(NumBits[resultType])); - clearText = (clearText + 1n) % 2n ** NumBits[resultType]; - insertSQL(handle, clearText); - break; - - case "VerifyCiphertext": - handle = event.args[0]; - try { - await getClearText(BigInt(handle)); - } catch { - throw Error("User input was not found in DB"); - } - break; - - case "FheIfThenElse": - handle = ethers.toBeHex(event.args[3], 32); - resultType = parseInt(handle.slice(-4, -2), 16); - handle = ethers.toBeHex(event.args[3], 32); - const clearControl = BigInt(await getClearText(event.args[0])); - const clearIfTrue = BigInt(await getClearText(event.args[1])); - const clearIfFalse = BigInt(await getClearText(event.args[2])); - if (clearControl === 1n) { - clearText = clearIfTrue; - } else { - clearText = clearIfFalse; - } - insertSQL(handle, clearText); - break; - - case "FheRand": - resultType = parseInt(event.args[0], 16); - handle = ethers.toBeHex(event.args[1], 32); - clearText = getRandomBigInt(Number(NumBits[resultType])); - insertSQL(handle, clearText, true); - counterRand++; - break; - - case "FheRandBounded": - resultType = parseInt(event.args[1], 16); - handle = ethers.toBeHex(event.args[2], 32); - clearText = getRandomBigInt(Number(log2(BigInt(event.args[0])))); - insertSQL(handle, clearText, true); - counterRand++; - break; - } -} - -export function getFHEGasFromTxReceipt(receipt: ethers.TransactionReceipt): number { - if (hre.network.name !== "hardhat") { - throw Error("FHEGas tracking is currently implemented only in mocked mode"); - } - if (receipt.status === 0) { - throw new Error("Transaction reverted"); - } - const contract = new ethers.Contract(executorAddress, abi, ethers.provider); - const relevantLogs = receipt.logs.filter((log: ethers.Log) => { - if (log.address.toLowerCase() !== executorAddress.toLowerCase()) { - return false; - } - try { - const parsedLog = contract.interface.parseLog({ - topics: log.topics, - data: log.data, - }); - return abi.some((item) => item.startsWith(`event ${parsedLog.name}`) && parsedLog.name !== "VerifyCiphertext"); - } catch { - return false; - } - }); - const FHELogs = relevantLogs.map((log: ethers.Log) => { - const parsedLog = contract.interface.parseLog({ - topics: log.topics, - data: log.data, - }); - return { - name: parsedLog.name, - args: parsedLog.args, - }; - }); - let FHEGasConsumed = 0; - for (const event of FHELogs) { - let type; - let handle; - switch (event.name) { - case "TrivialEncrypt": - type = parseInt(event.args[1], 16); - FHEGasConsumed += operatorsPrices["trivialEncrypt"].types[type]; - break; - - case "TrivialEncryptBytes": - type = parseInt(event.args[1], 16); - FHEGasConsumed += operatorsPrices["trivialEncrypt"].types[type]; - break; - - case "FheAdd": - handle = ethers.toBeHex(event.args[0], 32); - type = parseInt(handle.slice(-4, -2), 16); - if (event.args[2] === "0x01") { - FHEGasConsumed += operatorsPrices["fheAdd"].scalar[type]; - } else { - FHEGasConsumed += operatorsPrices["fheAdd"].nonScalar[type]; - } - break; - - case "FheSub": - handle = ethers.toBeHex(event.args[0], 32); - type = parseInt(handle.slice(-4, -2), 16); - if (event.args[2] === "0x01") { - FHEGasConsumed += operatorsPrices["fheSub"].scalar[type]; - } else { - FHEGasConsumed += operatorsPrices["fheSub"].nonScalar[type]; - } - break; - - case "FheMul": - handle = ethers.toBeHex(event.args[0], 32); - type = parseInt(handle.slice(-4, -2), 16); - if (event.args[2] === "0x01") { - FHEGasConsumed += operatorsPrices["fheMul"].scalar[type]; - } else { - FHEGasConsumed += operatorsPrices["fheMul"].nonScalar[type]; - } - break; - - case "FheDiv": - handle = ethers.toBeHex(event.args[0], 32); - type = parseInt(handle.slice(-4, -2), 16); - if (event.args[2] === "0x01") { - FHEGasConsumed += operatorsPrices["fheDiv"].scalar[type]; - } else { - throw new Error("Non-scalar div not implemented yet"); - } - break; - - case "FheRem": - handle = ethers.toBeHex(event.args[0], 32); - type = parseInt(handle.slice(-4, -2), 16); - if (event.args[2] === "0x01") { - FHEGasConsumed += operatorsPrices["fheRem"].scalar[type]; - } else { - throw new Error("Non-scalar rem not implemented yet"); - } - break; - - case "FheBitAnd": - handle = ethers.toBeHex(event.args[0], 32); - type = parseInt(handle.slice(-4, -2), 16); - if (event.args[2] === "0x01") { - FHEGasConsumed += operatorsPrices["fheBitAnd"].scalar[type]; - } else { - FHEGasConsumed += operatorsPrices["fheBitAnd"].nonScalar[type]; - } - break; - - case "FheBitOr": - handle = ethers.toBeHex(event.args[0], 32); - type = parseInt(handle.slice(-4, -2), 16); - if (event.args[2] === "0x01") { - FHEGasConsumed += operatorsPrices["fheBitOr"].scalar[type]; - } else { - FHEGasConsumed += operatorsPrices["fheBitOr"].nonScalar[type]; - } - break; - - case "FheBitXor": - handle = ethers.toBeHex(event.args[0], 32); - type = parseInt(handle.slice(-4, -2), 16); - if (event.args[2] === "0x01") { - FHEGasConsumed += operatorsPrices["fheBitXor"].scalar[type]; - } else { - FHEGasConsumed += operatorsPrices["fheBitXor"].nonScalar[type]; - } - break; - - case "FheShl": - handle = ethers.toBeHex(event.args[0], 32); - type = parseInt(handle.slice(-4, -2), 16); - if (event.args[2] === "0x01") { - FHEGasConsumed += operatorsPrices["fheBitShl"].scalar[type]; - } else { - FHEGasConsumed += operatorsPrices["fheBitShl"].nonScalar[type]; - } - break; - - case "FheShr": - handle = ethers.toBeHex(event.args[0], 32); - type = parseInt(handle.slice(-4, -2), 16); - if (event.args[2] === "0x01") { - FHEGasConsumed += operatorsPrices["fheBitShr"].scalar[type]; - } else { - FHEGasConsumed += operatorsPrices["fheBitShr"].nonScalar[type]; - } - break; - - case "FheRotl": - handle = ethers.toBeHex(event.args[0], 32); - type = parseInt(handle.slice(-4, -2), 16); - if (event.args[2] === "0x01") { - FHEGasConsumed += operatorsPrices["fheRotl"].scalar[type]; - } else { - FHEGasConsumed += operatorsPrices["fheRotl"].nonScalar[type]; - } - break; - - case "FheRotr": - handle = ethers.toBeHex(event.args[0], 32); - type = parseInt(handle.slice(-4, -2), 16); - if (event.args[2] === "0x01") { - FHEGasConsumed += operatorsPrices["fheRotr"].scalar[type]; - } else { - FHEGasConsumed += operatorsPrices["fheRotr"].nonScalar[type]; - } - break; - - case "FheEq": - handle = ethers.toBeHex(event.args[0], 32); - type = parseInt(handle.slice(-4, -2), 16); - if (event.args[2] === "0x01") { - FHEGasConsumed += operatorsPrices["fheEq"].scalar[type]; - } else { - FHEGasConsumed += operatorsPrices["fheEq"].nonScalar[type]; - } - break; - - case "FheEqBytes": - handle = ethers.toBeHex(event.args[0], 32); - type = parseInt(handle.slice(-4, -2), 16); - if (event.args[2] === "0x01") { - FHEGasConsumed += operatorsPrices["fheEq"].scalar[type]; - } else { - FHEGasConsumed += operatorsPrices["fheEq"].nonScalar[type]; - } - - case "FheNe": - handle = ethers.toBeHex(event.args[0], 32); - type = parseInt(handle.slice(-4, -2), 16); - if (event.args[2] === "0x01") { - FHEGasConsumed += operatorsPrices["fheNe"].scalar[type]; - } else { - FHEGasConsumed += operatorsPrices["fheNe"].nonScalar[type]; - } - break; - - case "FheNeBytes": - handle = ethers.toBeHex(event.args[0], 32); - type = parseInt(handle.slice(-4, -2), 16); - if (event.args[2] === "0x01") { - FHEGasConsumed += operatorsPrices["fheNe"].scalar[type]; - } else { - FHEGasConsumed += operatorsPrices["fheNe"].nonScalar[type]; - } - break; - - case "FheGe": - handle = ethers.toBeHex(event.args[0], 32); - type = parseInt(handle.slice(-4, -2), 16); - if (event.args[2] === "0x01") { - FHEGasConsumed += operatorsPrices["fheGe"].scalar[type]; - } else { - FHEGasConsumed += operatorsPrices["fheGe"].nonScalar[type]; - } - break; - - case "FheGt": - handle = ethers.toBeHex(event.args[0], 32); - type = parseInt(handle.slice(-4, -2), 16); - if (event.args[2] === "0x01") { - FHEGasConsumed += operatorsPrices["fheGt"].scalar[type]; - } else { - FHEGasConsumed += operatorsPrices["fheGt"].nonScalar[type]; - } - break; - - case "FheLe": - handle = ethers.toBeHex(event.args[0], 32); - type = parseInt(handle.slice(-4, -2), 16); - if (event.args[2] === "0x01") { - FHEGasConsumed += operatorsPrices["fheLe"].scalar[type]; - } else { - FHEGasConsumed += operatorsPrices["fheLe"].nonScalar[type]; - } - break; - - case "FheLt": - handle = ethers.toBeHex(event.args[0], 32); - type = parseInt(handle.slice(-4, -2), 16); - if (event.args[2] === "0x01") { - FHEGasConsumed += operatorsPrices["fheLt"].scalar[type]; - } else { - FHEGasConsumed += operatorsPrices["fheLt"].nonScalar[type]; - } - break; - - case "FheMax": - handle = ethers.toBeHex(event.args[0], 32); - type = parseInt(handle.slice(-4, -2), 16); - if (event.args[2] === "0x01") { - FHEGasConsumed += operatorsPrices["fheMax"].scalar[type]; - } else { - FHEGasConsumed += operatorsPrices["fheMax"].nonScalar[type]; - } - break; - - case "FheMin": - handle = ethers.toBeHex(event.args[0], 32); - type = parseInt(handle.slice(-4, -2), 16); - if (event.args[2] === "0x01") { - FHEGasConsumed += operatorsPrices["fheMin"].scalar[type]; - } else { - FHEGasConsumed += operatorsPrices["fheMin"].nonScalar[type]; - } - break; - - case "Cast": - handle = ethers.toBeHex(event.args[0], 32); - type = parseInt(handle.slice(-4, -2), 16); - FHEGasConsumed += operatorsPrices["cast"].types[type]; - break; - - case "FheNot": - handle = ethers.toBeHex(event.args[0], 32); - type = parseInt(handle.slice(-4, -2), 16); - FHEGasConsumed += operatorsPrices["fheNot"].types[type]; - break; - - case "FheNeg": - handle = ethers.toBeHex(event.args[0], 32); - type = parseInt(handle.slice(-4, -2), 16); - FHEGasConsumed += operatorsPrices["fheNeg"].types[type]; - break; - - case "FheIfThenElse": - handle = ethers.toBeHex(event.args[3], 32); - type = parseInt(handle.slice(-4, -2), 16); - FHEGasConsumed += operatorsPrices["ifThenElse"].types[type]; - break; - - case "FheRand": - type = parseInt(event.args[0], 16); - FHEGasConsumed += operatorsPrices["fheRand"].types[type]; - break; - - case "FheRandBounded": - type = parseInt(event.args[1], 16); - FHEGasConsumed += operatorsPrices["fheRandBounded"].types[type]; - break; - } - } - return FHEGasConsumed; -} diff --git a/contracts/test/decIdentity/diploma.ts b/contracts/test/decIdentity/diploma.ts deleted file mode 100644 index 5a31278..0000000 --- a/contracts/test/decIdentity/diploma.ts +++ /dev/null @@ -1,351 +0,0 @@ -import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers"; -import { toBufferBE } from "bigint-buffer"; -import { expect } from "chai"; -import type { FhevmInstance } from "fhevmjs"; - -import type { Diploma, EmployerClaim, IdMapping, PassportID } from "../../types"; -import { createInstance } from "../instance"; -import { reencryptEbool, reencryptEbytes64, reencryptEuint8, reencryptEuint16 } from "../reencrypt"; -import { getSigners, initSigners } from "../signers"; -import { bigIntToBytes64 } from "../utils"; -import { deployEmployerClaimFixture } from "./fixture/EmployerClaim.fixture"; - -/** - * Utility function to convert a bigint value to a 256-bit byte array - * @param value - The bigint value to convert - * @returns A Uint8Array representing the 256-bit byte array - */ -export const bigIntToBytes256 = (value: bigint) => { - return new Uint8Array(toBufferBE(value, 256)); -}; - -/** - * Integration test suite for PassportID and EmployerClaim contracts - * Tests the core functionality of diploma registration, verification and claim generation - */ -describe("Diploma", function () { - let passportID: PassportID; - let employerClaim: EmployerClaim; - let diplomaID: Diploma; - let idMapping: IdMapping; - - /** - * Initialize test signers before running any tests - * Sets up alice and other signers that will be used across test cases - */ - before(async function () { - await initSigners(); - this.signers = await getSigners(); - }); - - /** - * Deploy fresh contract instances before each test - * Sets up clean state with new PassportID, EmployerClaim, Diploma and IdMapping contracts - */ - beforeEach(async function () { - const deployment = await deployEmployerClaimFixture(); - employerClaim = deployment.employerClaim; - passportID = deployment.passportID; - diplomaID = deployment.diploma; - idMapping = deployment.idMapping; - - this.employerClaimAddress = await employerClaim.getAddress(); - this.diplomaAddress = await diplomaID.getAddress(); - this.passportIDAddress = await passportID.getAddress(); - this.idMappingAddress = await idMapping.getAddress(); - - this.instances = await createInstance(); - }); - - /** - * Helper function to register a diploma for a user - */ - async function registerDiploma( - userId: bigint, - instance: FhevmInstance, - diplomaAddress: string, - signer: HardhatEthersSigner, - university = bigIntToBytes64(8n), - degree = 8, - grade = bigIntToBytes64(8n), - ) { - const input = instance.createEncryptedInput(diplomaAddress, signer.address); - const encryptedData = await input.addBytes64(university).add16(degree).addBytes64(grade).encrypt(); - - await diplomaID - .connect(signer) - .registerDiploma( - userId, - encryptedData.handles[0], - encryptedData.handles[1], - encryptedData.handles[2], - encryptedData.inputProof, - ); - } - - // /** - // * Helper function to setup reencryption - // */ - // async function setupReencryption(instance: FhevmInstance, signer: HardhatEthersSigner, contractAddress: string) { - // const { publicKey, privateKey } = instance.generateKeypair(); - // const eip712 = instance.createEIP712(publicKey, contractAddress); - // const signature = await signer.signTypedData(eip712.domain, { Reencrypt: eip712.types.Reencrypt }, eip712.message); - - // return { publicKey, privateKey, signature: signature.replace("0x", "") }; - // } - - /** - * Helper function to register identity - */ - async function registerIdentity( - userId: bigint, - instance: FhevmInstance, - passportAddress: string, - signer: HardhatEthersSigner, - biodata = bigIntToBytes64(8n), - firstname = bigIntToBytes64(8n), - lastname = bigIntToBytes64(8n), - birthdate = 946681200n, // Sat Jan 01 2000 - 24 years old - ) { - const input = instance.createEncryptedInput(passportAddress, signer.address); - const encryptedData = await input - .addBytes64(biodata) - .addBytes64(firstname) - .addBytes64(lastname) - .add64(birthdate) - .encrypt(); - - await passportID - .connect(signer) - .registerIdentity( - userId, - encryptedData.handles[0], - encryptedData.handles[1], - encryptedData.handles[2], - encryptedData.handles[3], - encryptedData.inputProof, - ); - } - - it("should register an identity successfully", async function () { - await idMapping.connect(this.signers.alice).generateId(); - const userId = await idMapping.getId(this.signers.alice); - - await registerDiploma(userId, this.instances, this.diplomaAddress, this.signers.alice); - - expect(await diplomaID.registered(userId)); - }); - - it("should prevent duplicate registration for the same user", async function () { - await idMapping.connect(this.signers.alice).generateId(); - const userId = await idMapping.getId(this.signers.alice); - - await registerDiploma(userId, this.instances, this.diplomaAddress, this.signers.alice); - - await expect( - registerDiploma(userId, this.instances, this.diplomaAddress, this.signers.alice), - ).to.be.revertedWithCustomError(diplomaID, "DiplomaAlreadyRegistered"); - }); - - it("should retrieve the registered identity", async function () { - await idMapping.connect(this.signers.alice).generateId(); - const userId = await idMapping.getId(this.signers.alice); - - await registerDiploma(userId, this.instances, this.diplomaAddress, this.signers.alice); - - const universityHandleAlice = await diplomaID.getMyUniversity(userId); - - const reencryptedUniversity = await reencryptEbytes64( - this.signers, - this.instances, - "alice", - universityHandleAlice, - this.diplomaAddress, - ); - - expect(reencryptedUniversity).to.equal(8); - }); - - it("should generate an degree claim", async function () { - await idMapping.connect(this.signers.alice).generateId(); - const userId = await idMapping.getId(this.signers.alice); - - await registerDiploma(userId, this.instances, this.diplomaAddress, this.signers.alice); - - const tx = await diplomaID - .connect(this.signers.alice) - .generateClaim(this.employerClaimAddress, "generateDegreeClaim(uint256)"); - - await expect(tx).to.emit(employerClaim, "DegreeClaimGenerated"); - - const latestClaimUserId = await employerClaim.lastClaimId(); - const degreeClaim = await employerClaim.getDegreeClaim(latestClaimUserId); - - const reencryptedDegreeClaim = await reencryptEbool( - this.signers, - this.instances, - "alice", - degreeClaim, - this.diplomaAddress, - ); - - expect(reencryptedDegreeClaim).to.equal(0); - }); - - it("should generate both degree and adult claims", async function () { - await idMapping.connect(this.signers.alice).generateId(); - const userId = await idMapping.getId(this.signers.alice); - - await registerDiploma( - userId, - this.instances, - this.diplomaAddress, - this.signers.alice, - bigIntToBytes64(8n), - 3, // Computer Science (B.Sc) - bigIntToBytes64(8n), - ); - - const degreeTx = await diplomaID - .connect(this.signers.alice) - .generateClaim(this.employerClaimAddress, "generateDegreeClaim(uint256)"); - - await expect(degreeTx).to.emit(employerClaim, "DegreeClaimGenerated"); - - const latestDegreeClaimUserId = await employerClaim.lastClaimId(); - const degreeClaim = await employerClaim.getDegreeClaim(latestDegreeClaimUserId); - - await registerIdentity(userId, this.instances, this.passportIDAddress, this.signers.alice); - - const adultTx = await passportID - .connect(this.signers.alice) - .generateClaim(this.employerClaimAddress, "generateAdultClaim(uint256)"); - - await expect(adultTx).to.emit(employerClaim, "AdultClaimGenerated"); - - const latestAdultClaimUserId = await employerClaim.lastClaimId(); - const adultClaim = await employerClaim.getAdultClaim(latestAdultClaimUserId); - - const reencryptedDegreeClaim = await reencryptEbool( - this.signers, - this.instances, - "alice", - degreeClaim, - this.diplomaAddress, - ); - - const reencryptedAdultClaim = await reencryptEbool( - this.signers, - this.instances, - "alice", - adultClaim, - this.diplomaAddress, - ); - - expect(reencryptedDegreeClaim).to.equal(1); - expect(reencryptedAdultClaim).to.equal(1); - - await employerClaim.verifyClaims(userId, latestAdultClaimUserId, latestDegreeClaimUserId); - const verifyResult = await employerClaim.getVerifyClaim(userId); - - const reencryptedVerifyResult = await reencryptEbool( - this.signers, - this.instances, - "alice", - verifyResult, - this.diplomaAddress, - ); - - expect(reencryptedVerifyResult).to.equal(1); - }); - - it("should not allow generating claims without a registered ID", async function () { - // Try to generate degree claim without registering ID first - await expect( - diplomaID.connect(this.signers.alice).generateClaim(this.employerClaimAddress, "generateDegreeClaim(uint256)"), - ).to.be.revertedWithCustomError(idMapping, "NoIdGenerated"); - - // Try to generate adult claim without registering ID first - await expect( - passportID.connect(this.signers.alice).generateClaim(this.employerClaimAddress, "generateAdultClaim(uint256)"), - ).to.be.revertedWithCustomError(idMapping, "NoIdGenerated"); - }); - - it("should not allow generating claims with unregistered diploma/identity", async function () { - // Generate ID but don't register diploma/identity - await idMapping.connect(this.signers.alice).generateId(); - const userId = await idMapping.getId(this.signers.alice); - - // Try to generate degree claim without registering diploma - await expect( - diplomaID.connect(this.signers.alice).generateClaim(this.employerClaimAddress, "generateDegreeClaim(uint256)"), - ).to.be.revertedWith("sender isn't allowed"); - - // Try to generate adult claim without registering identity - await expect( - passportID.connect(this.signers.alice).generateClaim(this.employerClaimAddress, "generateAdultClaim(uint256)"), - ).to.be.revertedWith("sender isn't allowed"); - }); - - it("should allow admin to add a new registrar for diplomaID and passportID", async function () { - // Test diplomaID - await expect(diplomaID.connect(this.signers.alice).addRegistrar(this.signers.bob.address)) - .to.emit(diplomaID, "RoleGranted") - .withArgs(await diplomaID.REGISTRAR_ROLE(), this.signers.bob.address, this.signers.alice.address); - - expect(await diplomaID.hasRole(await diplomaID.REGISTRAR_ROLE(), this.signers.bob.address)).to.be.true; - - // Test passportID - await expect(passportID.connect(this.signers.alice).addRegistrar(this.signers.bob.address)) - .to.emit(passportID, "RoleGranted") - .withArgs(await passportID.REGISTRAR_ROLE(), this.signers.bob.address, this.signers.alice.address); - - expect(await passportID.hasRole(await passportID.REGISTRAR_ROLE(), this.signers.bob.address)).to.be.true; - }); - - it("should allow admin to remove a registrar from diplomaID and passportID", async function () { - // Test diplomaID - await diplomaID.connect(this.signers.alice).addRegistrar(this.signers.bob.address); - await expect(diplomaID.connect(this.signers.alice).removeRegistrar(this.signers.bob.address)) - .to.emit(diplomaID, "RoleRevoked") - .withArgs(await diplomaID.REGISTRAR_ROLE(), this.signers.bob.address, this.signers.alice.address); - - expect(await diplomaID.hasRole(await diplomaID.REGISTRAR_ROLE(), this.signers.bob.address)).to.be.false; - - // Test passportID - await passportID.connect(this.signers.alice).addRegistrar(this.signers.bob.address); - await expect(passportID.connect(this.signers.alice).removeRegistrar(this.signers.bob.address)) - .to.emit(passportID, "RoleRevoked") - .withArgs(await passportID.REGISTRAR_ROLE(), this.signers.bob.address, this.signers.alice.address); - - expect(await passportID.hasRole(await passportID.REGISTRAR_ROLE(), this.signers.bob.address)).to.be.false; - }); - - it("should not allow non-admin to add a registrar to diplomaID and passportID", async function () { - // Test diplomaID - await expect( - diplomaID.connect(this.signers.carol).addRegistrar(this.signers.carol.address), - ).to.be.revertedWithCustomError(diplomaID, "AccessControlUnauthorizedAccount"); - - // Test passportID - await expect( - passportID.connect(this.signers.carol).addRegistrar(this.signers.carol.address), - ).to.be.revertedWithCustomError(passportID, "AccessControlUnauthorizedAccount"); - }); - - it("should not allow non-admin to remove a registrar from diplomaID and passportID", async function () { - // Test diplomaID - await diplomaID.connect(this.signers.alice).addRegistrar(this.signers.bob.address); - await expect( - diplomaID.connect(this.signers.carol).removeRegistrar(this.signers.bob.address), - ).to.be.revertedWithCustomError(diplomaID, "AccessControlUnauthorizedAccount"); - await diplomaID.connect(this.signers.alice).removeRegistrar(this.signers.bob.address); - - // Test passportID - await passportID.connect(this.signers.alice).addRegistrar(this.signers.bob.address); - await expect( - passportID.connect(this.signers.carol).removeRegistrar(this.signers.bob.address), - ).to.be.revertedWithCustomError(passportID, "AccessControlUnauthorizedAccount"); - await passportID.connect(this.signers.alice).removeRegistrar(this.signers.bob.address); - }); -}); diff --git a/contracts/test/decIdentity/fixture/Diploma.fixture.ts b/contracts/test/decIdentity/fixture/Diploma.fixture.ts deleted file mode 100644 index ff0f4ba..0000000 --- a/contracts/test/decIdentity/fixture/Diploma.fixture.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { ethers } from "hardhat"; - -import type { Diploma, IdMapping } from "../../../types"; -import { getSigners } from "../../signers"; - -export async function deployDiplomaFixture(idMapping: IdMapping): Promise { - const signers = await getSigners(); - const contractFactory = await ethers.getContractFactory("Diploma"); - const contract = await contractFactory.connect(signers.alice).deploy(idMapping); - await contract.waitForDeployment(); - return contract; -} diff --git a/contracts/test/decIdentity/fixture/EmployerClaim.fixture.ts b/contracts/test/decIdentity/fixture/EmployerClaim.fixture.ts deleted file mode 100644 index 9e5cd42..0000000 --- a/contracts/test/decIdentity/fixture/EmployerClaim.fixture.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { ethers } from "hardhat"; - -import type { Diploma, EmployerClaim, IdMapping, PassportID } from "../../../types"; -import { deployDiplomaFixture } from "./Diploma.fixture"; -import { deployIdMappingFixture } from "./IdMapping.fixture"; -import { deployPassportIDFixture } from "./PassportID.fixture"; - -export async function deployEmployerClaimFixture(): Promise<{ - employerClaim: EmployerClaim; - passportID: PassportID; - diploma: Diploma; - idMapping: IdMapping; -}> { - const idMapping = await deployIdMappingFixture(); - const passportID = await deployPassportIDFixture(idMapping); - const diploma = await deployDiplomaFixture(idMapping); - const EmployerClaimFactory = await ethers.getContractFactory("EmployerClaim"); - const employerClaim = await EmployerClaimFactory.deploy(idMapping, passportID, diploma); - await employerClaim.waitForDeployment(); - return { employerClaim, passportID, diploma, idMapping }; -} diff --git a/contracts/test/decIdentity/fixture/IdMapping.fixture.ts b/contracts/test/decIdentity/fixture/IdMapping.fixture.ts deleted file mode 100644 index 2964ae9..0000000 --- a/contracts/test/decIdentity/fixture/IdMapping.fixture.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { ethers } from "hardhat"; - -import type { IdMapping } from "../../../types"; -import { getSigners } from "../../signers"; - -export async function deployIdMappingFixture(): Promise { - const signers = await getSigners(); - - const IdMappingFactory = await ethers.getContractFactory("IdMapping"); - const idMapping = await IdMappingFactory.connect(signers.alice).deploy(); - await idMapping.waitForDeployment(); - return idMapping; -} diff --git a/contracts/test/decIdentity/fixture/PassportID.fixture.ts b/contracts/test/decIdentity/fixture/PassportID.fixture.ts deleted file mode 100644 index 3657eb2..0000000 --- a/contracts/test/decIdentity/fixture/PassportID.fixture.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { ethers } from "hardhat"; - -import type { IdMapping, PassportID } from "../../../types"; -import { getSigners } from "../../signers"; - -export async function deployPassportIDFixture(idMapping: IdMapping): Promise { - const signers = await getSigners(); - const contractFactory = await ethers.getContractFactory("PassportID"); - const contract = await contractFactory.connect(signers.alice).deploy(idMapping); - await contract.waitForDeployment(); - return contract; -} diff --git a/contracts/test/decIdentity/idMapping.ts b/contracts/test/decIdentity/idMapping.ts deleted file mode 100644 index 6d7a25e..0000000 --- a/contracts/test/decIdentity/idMapping.ts +++ /dev/null @@ -1,106 +0,0 @@ -import { expect } from "chai"; -import { ethers } from "hardhat"; - -import type { IdMapping } from "../../types"; -import { createInstance } from "../instance"; -import { getSigners, initSigners } from "../signers"; -import { deployIdMappingFixture } from "./fixture/IdMapping.fixture"; - -describe("IdMapping Contract", function () { - let idMapping: IdMapping; - - before(async function () { - await initSigners(); - this.signers = await getSigners(); - }); - - beforeEach(async function () { - // Deploy the contract - idMapping = await deployIdMappingFixture(); - this.idMappingAddress = await idMapping.getAddress(); - - // Set up accounts - this.instances = await createInstance(); - }); - - it("Should set the ID for an address", async function () { - // Set ID for addr1 - await idMapping.generateId(); - - // Check if the ID was set correctly - expect(await idMapping.getId(this.signers.alice)).to.equal(1); - }); - - it("Should set IDs for multiple addresses", async function () { - // Set IDs for addr1 and addr2 - await idMapping.connect(this.signers.alice).generateId(); - await idMapping.connect(this.signers.bob).generateId(); - - // Verify each address has the correct ID - expect(await idMapping.getId(this.signers.alice)).to.equal(1); - expect(await idMapping.getId(this.signers.bob)).to.equal(2); - }); - - it("Should retrieve address for a given ID", async function () { - // Generate ID for alice - await idMapping.connect(this.signers.alice).generateId(); - - // Get alice's address using their ID (1) - const retrievedAddress = await idMapping.getAddr(1); - expect(retrievedAddress).to.equal(await this.signers.alice.getAddress()); - - // Verify getting an invalid ID reverts - await expect(idMapping.getAddr(999)).to.be.revertedWithCustomError(idMapping, "InvalidId"); - }); - - it("Should not allow generating multiple IDs for same address", async function () { - await idMapping.connect(this.signers.alice).generateId(); - await expect(idMapping.connect(this.signers.alice).generateId()).to.be.revertedWithCustomError( - idMapping, - "IdAlreadyGenerated", - ); - }); - - it("Should fail when getting ID for zero address", async function () { - await expect(idMapping.getId(ethers.ZeroAddress)).to.be.revertedWithCustomError(idMapping, "InvalidAddress"); - }); - - it("Should fail when getting ID for unregistered address", async function () { - await expect(idMapping.getId(this.signers.alice.address)).to.be.revertedWithCustomError(idMapping, "NoIdGenerated"); - }); - - it("Should fail when getting address for invalid ID", async function () { - await expect(idMapping.getAddr(0)).to.be.revertedWithCustomError(idMapping, "InvalidId"); - - await expect(idMapping.getAddr(999)).to.be.revertedWithCustomError(idMapping, "InvalidId"); - }); - - it("Should allow owner to reset ID for an address", async function () { - // Generate ID first - await idMapping.connect(this.signers.alice).generateId(); - const userId = await idMapping.getId(this.signers.alice.address); - - // Reset ID - await idMapping.resetIdForAddress(this.signers.alice.address); - - // Verify ID is reset - await expect(idMapping.getId(this.signers.alice.address)).to.be.revertedWithCustomError(idMapping, "NoIdGenerated"); - - await expect(idMapping.getAddr(userId)).to.be.revertedWithCustomError(idMapping, "NoAddressFound"); - }); - - it("Should not allow non-owner to reset ID", async function () { - await idMapping.connect(this.signers.alice).generateId(); - - await expect( - idMapping.connect(this.signers.bob).resetIdForAddress(this.signers.alice.address), - ).to.be.revertedWithCustomError(idMapping, "OwnableUnauthorizedAccount"); - }); - - it("Should not allow resetting ID for unregistered address", async function () { - await expect(idMapping.resetIdForAddress(this.signers.alice.address)).to.be.revertedWithCustomError( - idMapping, - "NoIdGenerated", - ); - }); -}); diff --git a/contracts/test/decIdentity/passportID.ts b/contracts/test/decIdentity/passportID.ts deleted file mode 100644 index abdf93b..0000000 --- a/contracts/test/decIdentity/passportID.ts +++ /dev/null @@ -1,164 +0,0 @@ -import "@nomicfoundation/hardhat-chai-matchers"; -import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers"; -import { toBufferBE } from "bigint-buffer"; -import { expect } from "chai"; -import type { FhevmInstance } from "fhevmjs"; - -import type { Diploma, EmployerClaim, IdMapping, PassportID } from "../../types"; -import { createInstance } from "../instance"; -import { reencryptEbool, reencryptEbytes64, reencryptEuint8 } from "../reencrypt"; -import { getSigners, initSigners } from "../signers"; -import { bigIntToBytes64 } from "../utils"; -import { deployEmployerClaimFixture } from "./fixture/EmployerClaim.fixture"; - -// Helper function to convert bigint to bytes -export const bigIntToBytes256 = (value: bigint) => { - return new Uint8Array(toBufferBE(value, 256)); -}; - -describe("PassportID", function () { - let passportID: PassportID; - let employerClaim: EmployerClaim; - let diplomaID: Diploma; - let idMapping: IdMapping; - - // Initialize signers before running tests - before(async function () { - await initSigners(); - this.signers = await getSigners(); - }); - - // Deploy fresh contract instances before each test - beforeEach(async function () { - const deployment = await deployEmployerClaimFixture(); - employerClaim = deployment.employerClaim; - passportID = deployment.passportID; - diplomaID = deployment.diploma; - idMapping = deployment.idMapping; - - this.employerClaimAddress = await employerClaim.getAddress(); - this.diplomaAddress = await diplomaID.getAddress(); - this.passportIDAddress = await passportID.getAddress(); - this.idMappingAddress = await idMapping.getAddress(); - - this.instances = await createInstance(); - }); - - // Helper function to register identity - async function registerIdentity( - userId: bigint, - instance: FhevmInstance, - passportAddress: string, - signer: HardhatEthersSigner, - biodata = bigIntToBytes64(8n), - firstname = bigIntToBytes64(8n), - lastname = bigIntToBytes64(8n), - birthdate = 946681200n, // Sat Jan 01 2000 - 24 years old - ) { - const input = instance.createEncryptedInput(passportAddress, signer.address); - const encryptedData = await input - .addBytes64(biodata) - .addBytes64(firstname) - .addBytes64(lastname) - .add64(birthdate) - .encrypt(); - - await passportID - .connect(signer) - .registerIdentity( - userId, - encryptedData.handles[0], - encryptedData.handles[1], - encryptedData.handles[2], - encryptedData.handles[3], - encryptedData.inputProof, - ); - } - - // Helper function to setup reencryption - async function setupReencryption(instance: FhevmInstance, signer: HardhatEthersSigner, contractAddress: string) { - const { publicKey, privateKey } = instance.generateKeypair(); - const eip712 = instance.createEIP712(publicKey, contractAddress); - const signature = await signer.signTypedData(eip712.domain, { Reencrypt: eip712.types.Reencrypt }, eip712.message); - - return { publicKey, privateKey, signature: signature.replace("0x", "") }; - } - - // Test case: Register an identity successfully - it("should register an identity successfully", async function () { - await idMapping.connect(this.signers.alice).generateId(); - const userId = await idMapping.getId(this.signers.alice); - - await registerIdentity(userId, this.instances, this.passportIDAddress, this.signers.alice); - - expect(await passportID.registered(this.signers.alice.address)); - }); - - // Test case: Prevent duplicate registration for the same user - it("should prevent duplicate registration for the same user", async function () { - await idMapping.connect(this.signers.alice).generateId(); - const userId = await idMapping.getId(this.signers.alice); - - await registerIdentity(userId, this.instances, this.passportIDAddress, this.signers.alice); - - await expect( - registerIdentity(userId, this.instances, this.passportIDAddress, this.signers.alice), - ).to.be.revertedWithCustomError(passportID, "AlreadyRegistered"); - }); - - // Test case: Retrieve the registered identity - it("should retrieve the registered identity", async function () { - await idMapping.connect(this.signers.alice).generateId(); - const userId = await idMapping.getId(this.signers.alice); - - await registerIdentity(userId, this.instances, this.passportIDAddress, this.signers.alice); - - const firstnameHandleAlice = await passportID.getMyIdentityFirstname(userId); - - const reencryptedFirstname = await reencryptEbytes64( - this.signers, - this.instances, - "alice", - firstnameHandleAlice, - this.diplomaAddress, - ); - - expect(reencryptedFirstname).to.equal(8); - }); - - // Test case: Generate an adult claim - it.only("should generate an adult claim", async function () { - await idMapping.connect(this.signers.alice).generateId(); - const userId = await idMapping.getId(this.signers.alice); - - await registerIdentity(userId, this.instances, this.passportIDAddress, this.signers.alice); - - const tx = await passportID - .connect(this.signers.alice) - .generateClaim(this.employerClaimAddress, "generateAdultClaim(uint256)"); - - await expect(tx).to.emit(employerClaim, "AdultClaimGenerated"); - - const latestClaimUserId = await employerClaim.lastClaimId(); - const adultsClaim = await employerClaim.getAdultClaim(latestClaimUserId); - const reencrypted = await reencryptEbool(this.signers, this.instances, "bob", adultsClaim, this.diplomaAddress); - - expect(reencrypted).to.equal(1); - }); - - // Test case: Should fail verification with invalid claim IDs - it("should fail verification with invalid claim IDs", async function () { - await idMapping.connect(this.signers.alice).generateId(); - const userId = await idMapping.getId(this.signers.alice); - - await expect(employerClaim.connect(this.signers.alice).verifyClaims(userId, 0, 1)).to.be.revertedWithCustomError( - employerClaim, - "InvalidClaimId", - ); - - await expect(employerClaim.connect(this.signers.alice).verifyClaims(userId, 1, 0)).to.be.revertedWithCustomError( - employerClaim, - "InvalidClaimId", - ); - }); -}); diff --git a/contracts/test/fhevmjsMocked.ts b/contracts/test/fhevmjsMocked.ts deleted file mode 100644 index ca6acd9..0000000 --- a/contracts/test/fhevmjsMocked.ts +++ /dev/null @@ -1,535 +0,0 @@ -import { toBigIntBE, toBufferBE } from "bigint-buffer"; -import crypto from "crypto"; -import { Wallet, ethers } from "ethers"; -import hre from "hardhat"; -import { Keccak } from "sha3"; -import { isAddress } from "web3-validator"; - -import { - ACL_ADDRESS, - INPUTVERIFIER_ADDRESS, - KMSVERIFIER_ADDRESS, - PRIVATE_KEY_COPROCESSOR_ACCOUNT, - PRIVATE_KEY_KMS_SIGNER, -} from "./constants"; -import { insertSQL } from "./coprocessorUtils"; -import { awaitCoprocessor, getClearText } from "./coprocessorUtils"; - -// const aclAdd = ACL_ADDRESS; - -enum Types { - ebool = 0, - euint4, - euint8, - euint16, - euint32, - euint64, - euint128, - eaddress, - euint256, - ebytes64, - ebytes128, - ebytes256, -} - -const sum = (arr: number[]) => arr.reduce((acc, val) => acc + val, 0); - -function bytesToBigInt(byteArray: Uint8Array): bigint { - if (!byteArray || byteArray?.length === 0) { - return BigInt(0); - } - const buffer = Buffer.from(byteArray); - const result = toBigIntBE(buffer); - return result; -} - -function createUintToUint8ArrayFunction(numBits: number) { - const numBytes = Math.ceil(numBits / 8); - return function (uint: number | bigint | boolean) { - const buffer = toBufferBE(BigInt(uint), numBytes); - - // concatenate 32 random bytes at the end of buffer to simulate encryption noise - const randomBytes = crypto.randomBytes(32); - const combinedBuffer = Buffer.concat([buffer, randomBytes]); - - let byteBuffer; - let totalBuffer; - - switch (numBits) { - case 2: // ebool takes 2 bits - byteBuffer = Buffer.from([Types.ebool]); - totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); - break; - case 4: - byteBuffer = Buffer.from([Types.euint4]); - totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); - break; - case 8: - byteBuffer = Buffer.from([Types.euint8]); - totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); - break; - case 16: - byteBuffer = Buffer.from([Types.euint16]); - totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); - break; - case 32: - byteBuffer = Buffer.from([Types.euint32]); - totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); - break; - case 64: - byteBuffer = Buffer.from([Types.euint64]); - totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); - break; - case 128: - byteBuffer = Buffer.from([Types.euint128]); - totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); - break; - case 160: - byteBuffer = Buffer.from([Types.eaddress]); - totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); - break; - case 256: - byteBuffer = Buffer.from([Types.euint256]); - totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); - break; - case 512: - byteBuffer = Buffer.from([Types.ebytes64]); - totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); - break; - case 1024: - byteBuffer = Buffer.from([Types.ebytes128]); - totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); - break; - case 2048: - byteBuffer = Buffer.from([Types.ebytes256]); - totalBuffer = Buffer.concat([byteBuffer, combinedBuffer]); - break; - default: - throw Error("Non-supported numBits"); - } - - return totalBuffer; - }; -} - -export const reencryptRequestMocked = async ( - handle: bigint, - privateKey: string, - publicKey: string, - signature: string, - contractAddress: string, - userAddress: string, -) => { - // Signature checking: - const domain = { - name: "Authorization token", - version: "1", - chainId: hre.network.config.chainId, - verifyingContract: contractAddress, - }; - const types = { - Reencrypt: [{ name: "publicKey", type: "bytes" }], - }; - const value = { - publicKey: `0x${publicKey}`, - }; - const signerAddress = ethers.verifyTypedData(domain, types, value, `0x${signature}`); - const normalizedSignerAddress = ethers.getAddress(signerAddress); - const normalizedUserAddress = ethers.getAddress(userAddress); - if (normalizedSignerAddress !== normalizedUserAddress) { - throw new Error("Invalid EIP-712 signature!"); - } - - // ACL checking - const aclArtifact = require("../node_modules/fhevm-core-contracts/artifacts/contracts/ACL.sol/ACL.json"); - const acl = await hre.ethers.getContractAt(aclArtifact.abi, ACL_ADDRESS); - const userAllowed = await acl.persistAllowed(handle, userAddress); - const contractAllowed = await acl.persistAllowed(handle, contractAddress); - const isAllowed = userAllowed && contractAllowed; - if (!isAllowed) { - throw new Error("User is not authorized to reencrypt this handle!"); - } - if (userAddress === contractAddress) { - throw new Error("userAddress should not be equal to contractAddress when requesting reencryption!"); - } - await awaitCoprocessor(); - return BigInt(await getClearText(handle)); -}; - -export const createEncryptedInputMocked = (contractAddress: string, userAddress: string) => { - if (!isAddress(contractAddress)) { - throw new Error("Contract address is not a valid address."); - } - - if (!isAddress(userAddress)) { - throw new Error("User address is not a valid address."); - } - - const values: bigint[] = []; - const bits: (keyof typeof ENCRYPTION_TYPES)[] = []; - return { - addBool(value: boolean | number | bigint) { - if (value == null) throw new Error("Missing value"); - if (typeof value !== "boolean" && typeof value !== "number" && typeof value !== "bigint") - throw new Error("The value must be a boolean, a number or a bigint."); - if ((typeof value !== "bigint" || typeof value !== "number") && Number(value) > 1) - throw new Error("The value must be 1 or 0."); - values.push(BigInt(value)); - bits.push(2); // ebool takes 2 bits instead of one: only exception in TFHE-rs - if (sum(bits) > 2048) throw Error("Packing more than 2048 bits in a single input ciphertext is unsupported"); - if (bits.length > 256) throw Error("Packing more than 256 variables in a single input ciphertext is unsupported"); - return this; - }, - add4(value: number | bigint) { - checkEncryptedValue(value, 4); - values.push(BigInt(value)); - bits.push(4); - if (sum(bits) > 2048) throw Error("Packing more than 2048 bits in a single input ciphertext is unsupported"); - if (bits.length > 256) throw Error("Packing more than 256 variables in a single input ciphertext is unsupported"); - return this; - }, - add8(value: number | bigint) { - checkEncryptedValue(value, 8); - values.push(BigInt(value)); - bits.push(8); - if (sum(bits) > 2048) throw Error("Packing more than 2048 bits in a single input ciphertext is unsupported"); - if (bits.length > 256) throw Error("Packing more than 256 variables in a single input ciphertext is unsupported"); - return this; - }, - add16(value: number | bigint) { - checkEncryptedValue(value, 16); - values.push(BigInt(value)); - bits.push(16); - if (sum(bits) > 2048) throw Error("Packing more than 2048 bits in a single input ciphertext is unsupported"); - if (bits.length > 256) throw Error("Packing more than 256 variables in a single input ciphertext is unsupported"); - return this; - }, - add32(value: number | bigint) { - checkEncryptedValue(value, 32); - values.push(BigInt(value)); - bits.push(32); - if (sum(bits) > 2048) throw Error("Packing more than 2048 bits in a single input ciphertext is unsupported"); - if (bits.length > 256) throw Error("Packing more than 256 variables in a single input ciphertext is unsupported"); - return this; - }, - add64(value: number | bigint) { - checkEncryptedValue(value, 64); - values.push(BigInt(value)); - bits.push(64); - if (sum(bits) > 2048) throw Error("Packing more than 2048 bits in a single input ciphertext is unsupported"); - if (bits.length > 256) throw Error("Packing more than 256 variables in a single input ciphertext is unsupported"); - return this; - }, - add128(value: number | bigint) { - checkEncryptedValue(value, 128); - values.push(BigInt(value)); - bits.push(128); - if (sum(bits) > 2048) throw Error("Packing more than 2048 bits in a single input ciphertext is unsupported"); - if (bits.length > 256) throw Error("Packing more than 256 variables in a single input ciphertext is unsupported"); - return this; - }, - addAddress(value: string) { - if (!isAddress(value)) { - throw new Error("The value must be a valid address."); - } - values.push(BigInt(value)); - bits.push(160); - if (sum(bits) > 2048) throw Error("Packing more than 2048 bits in a single input ciphertext is unsupported"); - if (bits.length > 256) throw Error("Packing more than 256 variables in a single input ciphertext is unsupported"); - return this; - }, - add256(value: number | bigint) { - checkEncryptedValue(value, 256); - values.push(BigInt(value)); - bits.push(256); - if (sum(bits) > 2048) throw Error("Packing more than 2048 bits in a single input ciphertext is unsupported"); - if (bits.length > 256) throw Error("Packing more than 256 variables in a single input ciphertext is unsupported"); - return this; - }, - addBytes64(value: Uint8Array) { - if (value.length !== 64) throw Error("Uncorrect length of input Uint8Array, should be 64 for an ebytes64"); - const bigIntValue = bytesToBigInt(value); - checkEncryptedValue(bigIntValue, 512); - values.push(bigIntValue); - bits.push(512); - if (sum(bits) > 2048) throw Error("Packing more than 2048 bits in a single input ciphertext is unsupported"); - if (bits.length > 256) throw Error("Packing more than 256 variables in a single input ciphertext is unsupported"); - return this; - }, - addBytes128(value: Uint8Array) { - if (value.length !== 128) throw Error("Uncorrect length of input Uint8Array, should be 128 for an ebytes128"); - const bigIntValue = bytesToBigInt(value); - checkEncryptedValue(bigIntValue, 1024); - values.push(bigIntValue); - bits.push(1024); - if (sum(bits) > 2048) throw Error("Packing more than 2048 bits in a single input ciphertext is unsupported"); - if (bits.length > 256) throw Error("Packing more than 256 variables in a single input ciphertext is unsupported"); - return this; - }, - addBytes256(value: Uint8Array) { - if (value.length !== 256) throw Error("Uncorrect length of input Uint8Array, should be 256 for an ebytes256"); - const bigIntValue = bytesToBigInt(value); - checkEncryptedValue(bigIntValue, 2048); - values.push(bigIntValue); - bits.push(2048); - if (sum(bits) > 2048) throw Error("Packing more than 2048 bits in a single input ciphertext is unsupported"); - if (bits.length > 256) throw Error("Packing more than 256 variables in a single input ciphertext is unsupported"); - return this; - }, - getValues() { - return values; - }, - getBits() { - return bits; - }, - resetValues() { - values.length = 0; - bits.length = 0; - return this; - }, - async encrypt() { - let encrypted = Buffer.alloc(0); - - bits.map((v, i) => { - encrypted = Buffer.concat([encrypted, createUintToUint8ArrayFunction(v)(values[i])]); - }); - - const encryptedArray = new Uint8Array(encrypted); - const hash = new Keccak(256).update(Buffer.from(encryptedArray)).digest(); - - const handles = bits.map((v, i) => { - const dataWithIndex = new Uint8Array(hash.length + 1); - dataWithIndex.set(hash, 0); - dataWithIndex.set([i], hash.length); - const finalHash = new Keccak(256).update(Buffer.from(dataWithIndex)).digest(); - const dataInput = new Uint8Array(32); - dataInput.set(finalHash, 0); - dataInput.set([i, ENCRYPTION_TYPES[v], 0], 29); - return dataInput; - }); - let inputProof = "0x" + numberToHex(handles.length); // for coprocessor : numHandles + numSignersKMS + hashCT + list_handles + signatureCopro + signatureKMSSigners (total len : 1+1+32+NUM_HANDLES*32+65+65*numSignersKMS) - // for native : numHandles + numSignersKMS + list_handles + signatureKMSSigners + bundleCiphertext (total len : 1+1+NUM_HANDLES*32+65*numSignersKMS+bundleCiphertext.length) - const numSigners = 1; // @note: only 1 signer in mocked mode for the moment - inputProof += numberToHex(numSigners); - //if (process.env.IS_COPROCESSOR === "true") { // @note: for now we support only the coprocessor mode, not native - // coprocessor - inputProof += hash.toString("hex"); - - const listHandlesStr = handles.map((i) => uint8ArrayToHexString(i)); - listHandlesStr.map((handle) => (inputProof += handle)); - const listHandles = listHandlesStr.map((i) => BigInt("0x" + i)); - const sigCoproc = await computeInputSignatureCopro( - "0x" + hash.toString("hex"), - listHandles, - userAddress, - contractAddress, - ); - inputProof += sigCoproc.slice(2); - - const signaturesKMS = await computeInputSignaturesKMS("0x" + hash.toString("hex"), userAddress, contractAddress); - signaturesKMS.map((sigKMS) => (inputProof += sigKMS.slice(2))); - listHandlesStr.map((handle, i) => insertSQL("0x" + handle, values[i])); - /*} else { - // native - const listHandlesStr = handles.map((i) => uint8ArrayToHexString(i)); - listHandlesStr.map((handle) => (inputProof += handle)); - const signaturesKMS = await computeInputSignaturesKMS( - "0x" + hash.toString("hex"), - userAddress, - contractAddress, - ); - signaturesKMS.map((sigKMS) => (inputProof += sigKMS.slice(2))); - listHandlesStr.map((handle, i) => insertSQL("0x" + handle, values[i])); - - inputProof += encrypted.toString("hex"); - }*/ - - return { - handles, - inputProof, - }; - }, - }; -}; - -function uint8ArrayToHexString(uint8Array: Uint8Array) { - return Array.from(uint8Array) - .map((byte) => byte.toString(16).padStart(2, "0")) - .join(""); -} - -function numberToHex(num: number) { - const hex = num.toString(16); - return hex.length % 2 ? "0" + hex : hex; -} - -const checkEncryptedValue = (value: number | bigint, bits: number) => { - if (value == null) throw new Error("Missing value"); - let limit; - if (bits >= 8) { - limit = BigInt(`0x${new Array(bits / 8).fill(null).reduce((v) => `${v}ff`, "")}`); - } else { - limit = BigInt(2 ** bits - 1); - } - if (typeof value !== "number" && typeof value !== "bigint") throw new Error("Value must be a number or a bigint."); - if (value > limit) { - throw new Error(`The value exceeds the limit for ${bits}bits integer (${limit.toString()}).`); - } -}; - -export const ENCRYPTION_TYPES = { - 2: 0, // ebool takes 2 bits - 4: 1, - 8: 2, - 16: 3, - 32: 4, - 64: 5, - 128: 6, - 160: 7, - 256: 8, - 512: 9, - 1024: 10, - 2048: 11, -}; - -async function computeInputSignatureCopro( - hash: string, - handlesList: bigint[], - userAddress: string, - contractAddress: string, -): Promise { - const privKeySigner = PRIVATE_KEY_COPROCESSOR_ACCOUNT; - const coprocSigner = new Wallet(privKeySigner).connect(ethers.provider); - const signature = await coprocSign(hash, handlesList, userAddress, contractAddress, coprocSigner); - return signature; -} - -async function computeInputSignaturesKMS( - hash: string, - userAddress: string, - contractAddress: string, -): Promise { - const signatures: string[] = []; - const numSigners = 1; // @note: only 1 KMS signer in mocked mode for now - for (let idx = 0; idx < numSigners; idx++) { - const privKeySigner = PRIVATE_KEY_KMS_SIGNER; - const kmsSigner = new ethers.Wallet(privKeySigner).connect(ethers.provider); - const signature = await kmsSign(hash, userAddress, contractAddress, kmsSigner); - signatures.push(signature); - } - return signatures; -} - -async function coprocSign( - hashOfCiphertext: string, - handlesList: bigint[], - userAddress: string, - contractAddress: string, - signer: Wallet, -): Promise { - const inputAdd = INPUTVERIFIER_ADDRESS; - const chainId = hre.__SOLIDITY_COVERAGE_RUNNING ? 31337 : network.config.chainId; - const aclAdd = ACL_ADDRESS; - - const domain = { - name: "InputVerifier", - version: "1", - chainId: chainId, - verifyingContract: inputAdd, - }; - - const types = { - CiphertextVerificationForCopro: [ - { - name: "aclAddress", - type: "address", - }, - { - name: "hashOfCiphertext", - type: "bytes32", - }, - { - name: "handlesList", - type: "uint256[]", - }, - { - name: "userAddress", - type: "address", - }, - { - name: "contractAddress", - type: "address", - }, - ], - }; - const message = { - aclAddress: aclAdd, - hashOfCiphertext: hashOfCiphertext, - handlesList: handlesList, - userAddress: userAddress, - contractAddress: contractAddress, - }; - - const signature = await signer.signTypedData(domain, types, message); - const sigRSV = ethers.Signature.from(signature); - const v = 27 + sigRSV.yParity; - const r = sigRSV.r; - const s = sigRSV.s; - - const result = r + s.substring(2) + v.toString(16); - return result; -} - -async function kmsSign( - hashOfCiphertext: string, - userAddress: string, - contractAddress: string, - signer: Wallet, -): Promise { - const kmsVerifierAdd = KMSVERIFIER_ADDRESS; - const chainId = hre.__SOLIDITY_COVERAGE_RUNNING ? 31337 : network.config.chainId; - const aclAdd = ACL_ADDRESS; - - const domain = { - name: "KMSVerifier", - version: "1", - chainId: chainId, - verifyingContract: kmsVerifierAdd, - }; - - const types = { - CiphertextVerificationForKMS: [ - { - name: "aclAddress", - type: "address", - }, - { - name: "hashOfCiphertext", - type: "bytes32", - }, - { - name: "userAddress", - type: "address", - }, - { - name: "contractAddress", - type: "address", - }, - ], - }; - const message = { - aclAddress: aclAdd, - hashOfCiphertext: hashOfCiphertext, - userAddress: userAddress, - contractAddress: contractAddress, - }; - - const signature = await signer.signTypedData(domain, types, message); - const sigRSV = ethers.Signature.from(signature); - const v = 27 + sigRSV.yParity; - const r = sigRSV.r; - const s = sigRSV.s; - - const result = r + s.substring(2) + v.toString(16); - return result; -} diff --git a/contracts/test/gatewayDecrypt/testAsyncDecrypt.ts b/contracts/test/gatewayDecrypt/testAsyncDecrypt.ts deleted file mode 100644 index 87696ce..0000000 --- a/contracts/test/gatewayDecrypt/testAsyncDecrypt.ts +++ /dev/null @@ -1,333 +0,0 @@ -import { expect } from "chai"; -import { ethers, network } from "hardhat"; - -import { awaitAllDecryptionResults, initGateway } from "../asyncDecrypt"; -import { createInstance } from "../instance"; -import { getSigners, initSigners } from "../signers"; -import { bigIntToBytes64, bigIntToBytes128, bigIntToBytes256 } from "../utils"; - -describe("TestAsyncDecrypt", function () { - before(async function () { - await initSigners(); - this.signers = await getSigners(); - await initGateway(); - }); - - beforeEach(async function () { - const contractFactory = await ethers.getContractFactory("TestAsyncDecrypt"); - this.contract = await contractFactory.connect(this.signers.alice).deploy(); - await this.contract.waitForDeployment(); - this.contractAddress = await this.contract.getAddress(); - this.fhevm = await createInstance(); - }); - - it("test async decrypt bool", async function () { - const tx2 = await this.contract.connect(this.signers.carol).requestBool(); - await tx2.wait(); - await awaitAllDecryptionResults(); - const y = await this.contract.yBool(); - expect(y).to.equal(true); - }); - - it("test async decrypt bool trustless", async function () { - const contractFactory = await ethers.getContractFactory("TestAsyncDecrypt"); - const contract2 = await contractFactory.connect(this.signers.alice).deploy(); - await contract2.waitForDeployment(); - const tx2 = await contract2.requestBoolTrustless(); - await tx2.wait(); - await awaitAllDecryptionResults(); - const y = await contract2.yBool(); - expect(y).to.equal(true); - }); - - it("test async decrypt bool would fail if maxTimestamp is above 1 day", async function () { - await expect(this.contract.connect(this.signers.carol).requestBoolAboveDelay()).to.be.revertedWith( - "maxTimestamp exceeded MAX_DELAY", - ); - }); - - it("test async decrypt uint4", async function () { - const tx2 = await this.contract.connect(this.signers.carol).requestUint4(); - await tx2.wait(); - await awaitAllDecryptionResults(); - const y = await this.contract.yUint4(); - expect(y).to.equal(4); - }); - - it("test async decrypt uint8", async function () { - const tx2 = await this.contract.connect(this.signers.carol).requestUint8(); - await tx2.wait(); - await awaitAllDecryptionResults(); - const y = await this.contract.yUint8(); - expect(y).to.equal(42); - }); - - it("test async decrypt uint16", async function () { - const tx2 = await this.contract.connect(this.signers.carol).requestUint16(); - await tx2.wait(); - await awaitAllDecryptionResults(); - const y = await this.contract.yUint16(); - expect(y).to.equal(16); - }); - - it("test async decrypt uint32", async function () { - const tx2 = await this.contract.connect(this.signers.carol).requestUint32(5, 15); - await tx2.wait(); - await awaitAllDecryptionResults(); - const y = await this.contract.yUint32(); - expect(y).to.equal(52); // 5+15+32 - }); - - it("test async decrypt uint64", async function () { - const tx2 = await this.contract.connect(this.signers.carol).requestUint64(); - await tx2.wait(); - await awaitAllDecryptionResults(); - const y = await this.contract.yUint64(); - expect(y).to.equal(18446744073709551600n); - }); - - it("test async decrypt uint128", async function () { - const tx2 = await this.contract.connect(this.signers.carol).requestUint128(); - await tx2.wait(); - await awaitAllDecryptionResults(); - const y = await this.contract.yUint128(); - expect(y).to.equal(1267650600228229401496703205443n); - }); - - it("test async decrypt uint128 non-trivial", async function () { - const inputAlice = this.fhevm.createEncryptedInput(this.contractAddress, this.signers.alice.address); - inputAlice.add128(184467440737095500429401496n); - const encryptedAmount = await inputAlice.encrypt(); - const tx = await this.contract.requestUint128NonTrivial(encryptedAmount.handles[0], encryptedAmount.inputProof); - await tx.wait(); - await awaitAllDecryptionResults(); - const y = await this.contract.yUint128(); - expect(y).to.equal(184467440737095500429401496n); - }); - - it("test async decrypt uint256", async function () { - const tx2 = await this.contract.connect(this.signers.carol).requestUint256(); - await tx2.wait(); - await awaitAllDecryptionResults(); - const y = await this.contract.yUint256(); - expect(y).to.equal(27606985387162255149739023449108101809804435888681546220650096895197251n); - }); - - it("test async decrypt uint256 non-trivial", async function () { - const inputAlice = this.fhevm.createEncryptedInput(this.contractAddress, this.signers.alice.address); - inputAlice.add256(6985387162255149739023449108101809804435888681546n); - const encryptedAmount = await inputAlice.encrypt(); - const tx = await this.contract.requestUint256NonTrivial(encryptedAmount.handles[0], encryptedAmount.inputProof); - await tx.wait(); - await awaitAllDecryptionResults(); - const y = await this.contract.yUint256(); - expect(y).to.equal(6985387162255149739023449108101809804435888681546n); - }); - - it("test async decrypt address", async function () { - const tx2 = await this.contract.connect(this.signers.carol).requestAddress(); - await tx2.wait(); - await awaitAllDecryptionResults(); - const y = await this.contract.yAddress(); - expect(y).to.equal("0x8ba1f109551bD432803012645Ac136ddd64DBA72"); - }); - - it("test async decrypt several addresses", async function () { - const tx2 = await this.contract.connect(this.signers.carol).requestSeveralAddresses(); - await tx2.wait(); - await awaitAllDecryptionResults(); - const y = await this.contract.yAddress(); - const y2 = await this.contract.yAddress2(); - expect(y).to.equal("0x8ba1f109551bD432803012645Ac136ddd64DBA72"); - expect(y2).to.equal("0xf48b8840387ba3809DAE990c930F3b4766A86ca3"); - }); - - it("test async decrypt mixed", async function () { - const tx2 = await this.contract.connect(this.signers.carol).requestMixed(5, 15); - await tx2.wait(); - await awaitAllDecryptionResults(); - let yB = await this.contract.yBool(); - expect(yB).to.equal(true); - let y = await this.contract.yUint4(); - expect(y).to.equal(4); - y = await this.contract.yUint8(); - expect(y).to.equal(42); - y = await this.contract.yUint16(); - expect(y).to.equal(16); - let yAdd = await this.contract.yAddress(); - expect(yAdd).to.equal("0x8ba1f109551bD432803012645Ac136ddd64DBA72"); - y = await this.contract.yUint32(); - expect(y).to.equal(52); // 5+15+32 - y = await this.contract.yUint64(); - expect(y).to.equal(18446744073709551600n); - }); - - it("test async decrypt uint64 non-trivial", async function () { - const inputAlice = this.fhevm.createEncryptedInput(this.contractAddress, this.signers.alice.address); - inputAlice.add64(18446744073709550042n); - const encryptedAmount = await inputAlice.encrypt(); - const tx = await this.contract.requestUint64NonTrivial(encryptedAmount.handles[0], encryptedAmount.inputProof); - await tx.wait(); - await awaitAllDecryptionResults(); - const y = await this.contract.yUint64(); - expect(y).to.equal(18446744073709550042n); - }); - - it("test async decrypt ebytes64 trivial", async function () { - const tx = await this.contract.requestEbytes64Trivial("0x78685689"); - await tx.wait(); - await awaitAllDecryptionResults(); - const y = await this.contract.yBytes64(); - expect(y).to.equal(ethers.toBeHex(BigInt("0x78685689"), 64)); - }); - - it("test async decrypt ebytes64 non-trivial", async function () { - const inputAlice = this.fhevm.createEncryptedInput(this.contractAddress, this.signers.alice.address); - inputAlice.addBytes64( - bigIntToBytes64(98870780878070870878787887072921111299111111000000292928818818818818221112111n), - ); - const encryptedAmount = await inputAlice.encrypt(); - const tx = await this.contract.requestEbytes64NonTrivial(encryptedAmount.handles[0], encryptedAmount.inputProof); - await tx.wait(); - await awaitAllDecryptionResults(); - const y = await this.contract.yBytes64(); - expect(y).to.equal( - ethers.toBeHex(98870780878070870878787887072921111299111111000000292928818818818818221112111n, 64), - ); - }); - - it("test async decrypt ebytes128 trivial", async function () { - const tx = await this.contract.requestEbytes128Trivial( - "0x8701d11594415047dfac2d9cb87e6631df5a735a2f364fba1511fa7b812dfad2972b809b80ff25ec19591a598081af357cba384cf5aa8e085678ff70bc55faee", - ); - await tx.wait(); - await awaitAllDecryptionResults(); - const y = await this.contract.yBytes128(); - expect(y).to.equal( - ethers.toBeHex( - BigInt( - "0x8701d11594415047dfac2d9cb87e6631df5a735a2f364fba1511fa7b812dfad2972b809b80ff25ec19591a598081af357cba384cf5aa8e085678ff70bc55faee", - ), - 128, - ), - ); - }); - - it("test async decrypt ebytes128 non-trivial", async function () { - const inputAlice = this.fhevm.createEncryptedInput(this.contractAddress, this.signers.alice.address); - inputAlice.addBytes128( - bigIntToBytes128( - 9887078087807087087878788707292111129911111100000029292881881881881822111211198870780878070870878787887072921111299111111000000292928818818818818221112111n, - ), - ); - const encryptedAmount = await inputAlice.encrypt(); - const tx = await this.contract.requestEbytes128NonTrivial(encryptedAmount.handles[0], encryptedAmount.inputProof); - await tx.wait(); - await awaitAllDecryptionResults(); - const y = await this.contract.yBytes128(); - expect(y).to.equal( - ethers.toBeHex( - 9887078087807087087878788707292111129911111100000029292881881881881822111211198870780878070870878787887072921111299111111000000292928818818818818221112111n, - 128, - ), - ); - }); - - it("test async decrypt ebytes256 trivial", async function () { - const tx = await this.contract.requestEbytes256Trivial("0x78685689"); - await tx.wait(); - await awaitAllDecryptionResults(); - const y = await this.contract.yBytes256(); - expect(y).to.equal(ethers.toBeHex(BigInt("0x78685689"), 256)); - }); - - it("test async decrypt ebytes256 non-trivial", async function () { - const inputAlice = this.fhevm.createEncryptedInput(this.contractAddress, this.signers.alice.address); - inputAlice.addBytes256(bigIntToBytes256(18446744073709550022n)); - const encryptedAmount = await inputAlice.encrypt(); - const tx = await this.contract.requestEbytes256NonTrivial(encryptedAmount.handles[0], encryptedAmount.inputProof); - await tx.wait(); - await awaitAllDecryptionResults(); - const y = await this.contract.yBytes256(); - expect(y).to.equal(ethers.toBeHex(18446744073709550022n, 256)); - }); - - it("test async decrypt ebytes256 non-trivial with snapshot [skip-on-coverage]", async function () { - if (network.name === "hardhat") { - this.snapshotId = await ethers.provider.send("evm_snapshot"); - const inputAlice = this.fhevm.createEncryptedInput(this.contractAddress, this.signers.alice.address); - inputAlice.addBytes256(bigIntToBytes256(18446744073709550022n)); - const encryptedAmount = await inputAlice.encrypt(); - const tx = await this.contract.requestEbytes256NonTrivial(encryptedAmount.handles[0], encryptedAmount.inputProof); - await tx.wait(); - await awaitAllDecryptionResults(); - const y = await this.contract.yBytes256(); - expect(y).to.equal(ethers.toBeHex(18446744073709550022n, 256)); - - await ethers.provider.send("evm_revert", [this.snapshotId]); - const inputAlice2 = this.fhevm.createEncryptedInput(this.contractAddress, this.signers.alice.address); - inputAlice2.addBytes256(bigIntToBytes256(424242n)); - const encryptedAmount2 = await inputAlice2.encrypt(); - const tx2 = await this.contract.requestEbytes256NonTrivial( - encryptedAmount2.handles[0], - encryptedAmount2.inputProof, - ); - await tx2.wait(); - await awaitAllDecryptionResults(); - const y2 = await this.contract.yBytes256(); - expect(y2).to.equal(ethers.toBeHex(424242n, 256)); - } - }); - - it("test async decrypt mixed with ebytes256", async function () { - const inputAlice = this.fhevm.createEncryptedInput(this.contractAddress, this.signers.alice.address); - inputAlice.addBytes256(bigIntToBytes256(18446744073709550032n)); - const encryptedAmount = await inputAlice.encrypt(); - const tx = await this.contract.requestMixedBytes256(encryptedAmount.handles[0], encryptedAmount.inputProof); - await tx.wait(); - await awaitAllDecryptionResults(); - const y = await this.contract.yBytes256(); - expect(y).to.equal(ethers.toBeHex(18446744073709550032n, 256)); - const y2 = await this.contract.yBytes64(); - expect(y2).to.equal(ethers.toBeHex(BigInt("0xaaff42"), 64)); - const yb = await this.contract.yBool(); - expect(yb).to.equal(true); - const yAdd = await this.contract.yAddress(); - expect(yAdd).to.equal("0x8ba1f109551bD432803012645Ac136ddd64DBA72"); - }); - - it("test async decrypt ebytes256 non-trivial trustless", async function () { - const contractFactory = await ethers.getContractFactory("TestAsyncDecrypt"); - const contract2 = await contractFactory.connect(this.signers.alice).deploy(); - await contract2.waitForDeployment(); - const inputAlice = this.fhevm.createEncryptedInput(await contract2.getAddress(), this.signers.alice.address); - inputAlice.addBytes256(bigIntToBytes256(18446744073709550022n)); - const encryptedAmount = await inputAlice.encrypt(); - const tx = await contract2.requestEbytes256NonTrivialTrustless( - encryptedAmount.handles[0], - encryptedAmount.inputProof, - ); - await tx.wait(); - await awaitAllDecryptionResults(); - const y = await contract2.yBytes256(); - expect(y).to.equal(ethers.toBeHex(18446744073709550022n, 256)); - }); - - it("test async decrypt mixed with ebytes256 trustless", async function () { - const contractFactory = await ethers.getContractFactory("TestAsyncDecrypt"); - const contract2 = await contractFactory.connect(this.signers.alice).deploy(); - await contract2.waitForDeployment(); - const inputAlice = this.fhevm.createEncryptedInput(await contract2.getAddress(), this.signers.alice.address); - inputAlice.addBytes256(bigIntToBytes256(18446744073709550032n)); - const encryptedAmount = await inputAlice.encrypt(); - const tx = await contract2.requestMixedBytes256Trustless(encryptedAmount.handles[0], encryptedAmount.inputProof); - await tx.wait(); - await awaitAllDecryptionResults(); - const y = await contract2.yBytes256(); - expect(y).to.equal(ethers.toBeHex(18446744073709550032n, 256)); - const yb = await contract2.yBool(); - expect(yb).to.equal(true); - const yAdd = await contract2.yAddress(); - expect(yAdd).to.equal("0x8ba1f109551bD432803012645Ac136ddd64DBA72"); - }); -}); diff --git a/contracts/test/instance.ts b/contracts/test/instance.ts deleted file mode 100644 index e310c2b..0000000 --- a/contracts/test/instance.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { createEIP712, createInstance as createFhevmInstance, generateKeypair } from "fhevmjs"; -import { FhevmInstance } from "fhevmjs/node"; -import { network } from "hardhat"; - -import { ACL_ADDRESS, GATEWAY_URL, KMSVERIFIER_ADDRESS } from "./constants"; -import { createEncryptedInputMocked, reencryptRequestMocked } from "./fhevmjsMocked"; - -const kmsAdd = KMSVERIFIER_ADDRESS; -const aclAdd = ACL_ADDRESS; - -export const createInstance = async (): Promise => { - if (network.name === "hardhat") { - const instance = { - reencrypt: reencryptRequestMocked, - createEncryptedInput: createEncryptedInputMocked, - getPublicKey: () => "0xFFAA44433", - generateKeypair: generateKeypair, - createEIP712: createEIP712(network.config.chainId), - }; - return instance; - } else { - const instance = await createFhevmInstance({ - kmsContractAddress: kmsAdd, - aclContractAddress: aclAdd, - networkUrl: network.config.url, - gatewayUrl: GATEWAY_URL, - }); - return instance; - } -}; diff --git a/contracts/test/mockedSetup.ts b/contracts/test/mockedSetup.ts deleted file mode 100644 index b541640..0000000 --- a/contracts/test/mockedSetup.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { HardhatRuntimeEnvironment } from "hardhat/types"; - -import { - ACL_ADDRESS, - FHEPAYMENT_ADDRESS, - GATEWAYCONTRACT_ADDRESS, - INPUTVERIFIER_ADDRESS, - KMSVERIFIER_ADDRESS, - PRIVATE_KEY_KMS_SIGNER, - TFHEEXECUTOR_ADDRESS, -} from "./constants"; - -const nullAddress = "0x0000000000000000000000000000000000000000"; -const oneAddress = "0x0000000000000000000000000000000000000001"; - -export async function setCodeMocked(hre: any): Promise { - const aclArtifact = await import("../node_modules/fhevm-core-contracts/artifacts/contracts/ACL.sol/ACL.json"); - const aclBytecode = aclArtifact.default.deployedBytecode; - await hre.network.provider.send("hardhat_setCode", [ACL_ADDRESS, aclBytecode]); - const execArtifact = await import( - "../node_modules/fhevm-core-contracts/artifacts/contracts/TFHEExecutorWithEvents.sol/TFHEExecutorWithEvents.json" - ); - const execBytecode = execArtifact.default.deployedBytecode; - await hre.network.provider.send("hardhat_setCode", [TFHEEXECUTOR_ADDRESS, execBytecode]); - const kmsArtifact = await import( - "../node_modules/fhevm-core-contracts/artifacts/contracts/KMSVerifier.sol/KMSVerifier.json" - ); - const kmsBytecode = kmsArtifact.default.deployedBytecode; - await hre.network.provider.send("hardhat_setCode", [KMSVERIFIER_ADDRESS, kmsBytecode]); - const inputArtifact = await import( - "../node_modules/fhevm-core-contracts/artifacts/contracts/InputVerifier.coprocessor.sol/InputVerifier.json" - ); - const inputBytecode = inputArtifact.default.deployedBytecode; - await hre.network.provider.send("hardhat_setCode", [INPUTVERIFIER_ADDRESS, inputBytecode]); - const fhepaymentArtifact = await import( - "../node_modules/fhevm-core-contracts/artifacts/contracts/FHEPayment.sol/FHEPayment.json" - ); - const fhepaymentBytecode = fhepaymentArtifact.default.deployedBytecode; - await hre.network.provider.send("hardhat_setCode", [FHEPAYMENT_ADDRESS, fhepaymentBytecode]); - const gatewayArtifact = await import( - "../node_modules/fhevm-core-contracts/artifacts/gateway/GatewayContract.sol/GatewayContract.json" - ); - const gatewayBytecode = gatewayArtifact.default.deployedBytecode; - await hre.network.provider.send("hardhat_setCode", [GATEWAYCONTRACT_ADDRESS, gatewayBytecode]); - const zero = await impersonateNullAddress(hre); - const one = await impersonateOneAddress(hre); - const kmsSigner = new hre.ethers.Wallet(PRIVATE_KEY_KMS_SIGNER); - const kms = await hre.ethers.getContractAt(kmsArtifact.abi, KMSVERIFIER_ADDRESS); - await kms.connect(zero).initialize(oneAddress); - await kms.connect(one).addSigner(kmsSigner); - const input = await hre.ethers.getContractAt(inputArtifact.abi, INPUTVERIFIER_ADDRESS); - await input.connect(zero).initialize(oneAddress); - const gateway = await hre.ethers.getContractAt(gatewayArtifact.abi, GATEWAYCONTRACT_ADDRESS); - await gateway.connect(zero).addRelayer(nullAddress); -} - -let initNull = false; -async function impersonateNullAddress(hre: HardhatRuntimeEnvironment) { - // for mocked mode - await hre.network.provider.request({ - method: "hardhat_impersonateAccount", - params: [nullAddress], - }); - if (!initNull) { - await hre.network.provider.send("hardhat_setBalance", [ - nullAddress, - "0x56BC75E2D63100000", // 100 ETH in hex - ]); - initNull = true; - } - const nullSigner = await hre.ethers.getSigner(nullAddress); - return nullSigner; -} - -let initOne = false; -async function impersonateOneAddress(hre: HardhatRuntimeEnvironment) { - // for mocked mode - await hre.network.provider.request({ - method: "hardhat_impersonateAccount", - params: [oneAddress], - }); - if (!initOne) { - await hre.network.provider.send("hardhat_setBalance", [ - oneAddress, - "0x56BC75E2D63100000", // 100 ETH in hex - ]); - initOne = true; - } - const oneSigner = await hre.ethers.getSigner(oneAddress); - return oneSigner; -} diff --git a/contracts/test/operatorsPrices.json b/contracts/test/operatorsPrices.json deleted file mode 100644 index d7f31a6..0000000 --- a/contracts/test/operatorsPrices.json +++ /dev/null @@ -1,218 +0,0 @@ -{ - "fheAdd": { - "binary": true, - "scalar": { "1": 65000, "2": 94000, "3": 133000, "4": 162000, "5": 188000, "6": 218000, "8": 253000 }, - "nonScalar": { "1": 65000, "2": 94000, "3": 133000, "4": 162000, "5": 188000, "6": 218000, "8": 253000 } - }, - "fheSub": { - "binary": true, - "scalar": { "1": 65000, "2": 94000, "3": 133000, "4": 162000, "5": 188000, "6": 218000, "8": 253000 }, - "nonScalar": { "1": 65000, "2": 94000, "3": 133000, "4": 162000, "5": 188000, "6": 218000, "8": 253000 } - }, - "fheMul": { - "binary": true, - "scalar": { "1": 88000, "2": 159000, "3": 208000, "4": 264000, "5": 356000, "6": 480000, "8": 647000 }, - "nonScalar": { "1": 150000, "2": 197000, "3": 262000, "4": 359000, "5": 641000, "6": 1145000, "8": 2045000 } - }, - "fheDiv": { - "binary": true, - "scalar": { "1": 139000, "2": 238000, "3": 314000, "4": 398000, "5": 584000, "6": 857000, "8": 1258000 } - }, - "fheRem": { - "binary": true, - "scalar": { "1": 286000, "2": 460000, "3": 622000, "4": 805000, "5": 1095000, "6": 1499000, "8": 2052000 } - }, - "fheBitAnd": { - "binary": true, - "scalar": { "0": 26000, "1": 32000, "2": 34000, "3": 34000, "4": 35000, "5": 38000, "6": 41000, "8": 44000 }, - "nonScalar": { "0": 26000, "1": 32000, "2": 34000, "3": 34000, "4": 35000, "5": 38000, "6": 41000, "8": 44000 } - }, - "fheBitOr": { - "binary": true, - "scalar": { "0": 26000, "1": 32000, "2": 34000, "3": 34000, "4": 35000, "5": 38000, "6": 41000, "8": 44000 }, - "nonScalar": { "0": 26000, "1": 32000, "2": 34000, "3": 34000, "4": 35000, "5": 38000, "6": 41000, "8": 44000 } - }, - "fheBitXor": { - "binary": true, - "scalar": { "0": 26000, "1": 32000, "2": 34000, "3": 34000, "4": 35000, "5": 38000, "6": 41000, "8": 44000 }, - "nonScalar": { "0": 26000, "1": 32000, "2": 34000, "3": 34000, "4": 35000, "5": 38000, "6": 41000, "8": 44000 } - }, - "fheShl": { - "binary": true, - "scalar": { "1": 35000, "2": 35000, "3": 35000, "4": 35000, "5": 38000, "6": 41000, "8": 44000 }, - "nonScalar": { "1": 116000, "2": 133000, "3": 153000, "4": 183000, "5": 227000, "6": 282000, "8": 350000 } - }, - "fheShr": { - "binary": true, - "scalar": { "1": 35000, "2": 35000, "3": 35000, "4": 35000, "5": 38000, "6": 41000, "8": 44000 }, - "nonScalar": { "1": 116000, "2": 133000, "3": 153000, "4": 183000, "5": 227000, "6": 282000, "8": 350000 } - }, - "fheRotl": { - "binary": true, - "scalar": { "1": 35000, "2": 35000, "3": 35000, "4": 35000, "5": 38000, "6": 41000, "8": 44000 }, - "nonScalar": { "1": 116000, "2": 133000, "3": 153000, "4": 183000, "5": 227000, "6": 282000, "8": 350000 } - }, - "fheRotr": { - "binary": true, - "scalar": { "1": 35000, "2": 35000, "3": 35000, "4": 35000, "5": 38000, "6": 41000, "8": 44000 }, - "nonScalar": { "1": 116000, "2": 133000, "3": 153000, "4": 183000, "5": 227000, "6": 282000, "8": 350000 } - }, - "fheEq": { - "binary": true, - "scalar": { - "0": 49000, - "1": 51000, - "2": 53000, - "3": 54000, - "4": 82000, - "5": 86000, - "6": 88000, - "7": 90000, - "8": 100000, - "9": 150000, - "10": 200000, - "11": 300000 - }, - "nonScalar": { - "0": 49000, - "1": 51000, - "2": 53000, - "3": 54000, - "4": 82000, - "5": 86000, - "6": 88000, - "7": 90000, - "8": 100000, - "9": 150000, - "10": 200000, - "11": 300000 - } - }, - "fheNe": { - "binary": true, - "scalar": { - "0": 49000, - "1": 51000, - "2": 53000, - "3": 54000, - "4": 82000, - "5": 86000, - "6": 88000, - "7": 90000, - "8": 100000, - "9": 150000, - "10": 200000, - "11": 300000 - }, - "nonScalar": { - "0": 49000, - "1": 51000, - "2": 53000, - "3": 54000, - "4": 82000, - "5": 86000, - "6": 88000, - "7": 90000, - "8": 100000, - "9": 150000, - "10": 200000, - "11": 300000 - } - }, - "fheGe": { - "binary": true, - "scalar": { "1": 70000, "2": 82000, "3": 105000, "4": 128000, "5": 156000, "6": 190000, "8": 231000 }, - "nonScalar": { "1": 70000, "2": 82000, "3": 105000, "4": 128000, "5": 156000, "6": 190000, "8": 231000 } - }, - "fheGt": { - "binary": true, - "scalar": { "1": 70000, "2": 82000, "3": 105000, "4": 128000, "5": 156000, "6": 190000, "8": 231000 }, - "nonScalar": { "1": 70000, "2": 82000, "3": 105000, "4": 128000, "5": 156000, "6": 190000, "8": 231000 } - }, - "fheLe": { - "binary": true, - "scalar": { "1": 70000, "2": 82000, "3": 105000, "4": 128000, "5": 156000, "6": 190000, "8": 231000 }, - "nonScalar": { "1": 70000, "2": 82000, "3": 105000, "4": 128000, "5": 156000, "6": 190000, "8": 231000 } - }, - "fheLt": { - "binary": true, - "scalar": { "1": 70000, "2": 82000, "3": 105000, "4": 128000, "5": 156000, "6": 190000, "8": 231000 }, - "nonScalar": { "1": 70000, "2": 82000, "3": 105000, "4": 128000, "5": 156000, "6": 190000, "8": 231000 } - }, - "fheMin": { - "binary": true, - "scalar": { "1": 121000, "2": 128000, "3": 150000, "4": 164000, "5": 192000, "6": 225000, "8": 264000 }, - "nonScalar": { "1": 121000, "2": 128000, "3": 153000, "4": 183000, "5": 210000, "6": 241000, "8": 277000 } - }, - "fheMax": { - "binary": true, - "scalar": { "1": 121000, "2": 128000, "3": 150000, "4": 164000, "5": 192000, "6": 225000, "8": 264000 }, - "nonScalar": { "1": 121000, "2": 128000, "3": 153000, "4": 183000, "5": 210000, "6": 241000, "8": 277000 } - }, - "fheNeg": { - "binary": false, - "types": { "1": 60000, "2": 95000, "3": 131000, "4": 160000, "5": 199000, "6": 248000, "8": 309000 } - }, - "fheNot": { - "binary": false, - "types": { "0": 30000, "1": 33000, "2": 34000, "3": 35000, "4": 36000, "5": 37000, "6": 38000, "8": 39000 } - }, - "cast": { - "binary": false, - "types": { "0": 200, "1": 200, "2": 200, "3": 200, "4": 200, "5": 200, "6": 200, "8": 200 } - }, - "trivialEncrypt": { - "binary": false, - "types": { - "0": 100, - "1": 100, - "2": 100, - "3": 200, - "4": 300, - "5": 600, - "6": 650, - "7": 700, - "8": 800, - "9": 1600, - "10": 3200, - "11": 6400 - } - }, - "ifThenElse": { - "binary": false, - "types": { - "0": 43000, - "1": 45000, - "2": 47000, - "3": 47000, - "4": 50000, - "5": 53000, - "6": 70000, - "7": 80000, - "8": 90000, - "9": 150000, - "10": 200000, - "11": 300000 - } - }, - "fheRand": { - "binary": false, - "types": { - "0": 100000, - "1": 100000, - "2": 100000, - "3": 100000, - "4": 100000, - "5": 100000, - "6": 100000, - "8": 100000, - "9": 200000, - "10": 300000, - "11": 400000 - } - }, - "fheRandBounded": { - "binary": false, - "types": { "1": 100000, "2": 100000, "3": 100000, "4": 100000, "5": 100000, "6": 100000, "8": 100000 } - } -} diff --git a/contracts/test/reencrypt.ts b/contracts/test/reencrypt.ts deleted file mode 100644 index c81093f..0000000 --- a/contracts/test/reencrypt.ts +++ /dev/null @@ -1,200 +0,0 @@ -import { FhevmInstance } from "fhevmjs/node"; - -import { ACCOUNT_NAMES } from "./constants"; -import { Signers } from "./signers"; - -const EBOOL_T = 0; -const EUINT4_T = 1; -const EUINT8_T = 2; -const EUINT16_T = 3; -const EUINT32_T = 4; -const EUINT64_T = 5; -const EUINT128_T = 6; -const EUINT160_T = 7; // @dev It is the one for eaddresses. -const EUINT256_T = 8; -const EBYTES64_T = 9; -const EBYTES128_T = 10; -const EBYTES256_T = 11; - -type AccountName = (typeof ACCOUNT_NAMES)[number]; - -export function verifyType(handle: bigint, expectedType: number) { - if (handle === 0n) { - throw "Handle is not initialized"; - } - - if (handle.toString(2).length > 256) { - throw "Handle is not a bytes32"; - } - - const typeCt = handle >> 8n; - - if (Number(typeCt % 256n) !== expectedType) { - throw "Wrong encrypted type for the handle"; - } -} - -export async function reencryptEbool( - signers: Signers, - instances: FhevmInstance, - user: AccountName, - handle: bigint, - contractAddress: string, -): Promise { - verifyType(handle, EBOOL_T); - return (await reencryptHandle(signers, instances, user, handle, contractAddress)) === 1n; -} - -export async function reencryptEuint4( - signers: Signers, - instances: FhevmInstance, - user: AccountName, - handle: bigint, - contractAddress: string, -): Promise { - verifyType(handle, EUINT4_T); - return reencryptHandle(signers, instances, user, handle, contractAddress); -} - -export async function reencryptEuint8( - signers: Signers, - instances: FhevmInstance, - user: AccountName, - handle: bigint, - contractAddress: string, -): Promise { - verifyType(handle, EUINT8_T); - return reencryptHandle(signers, instances, user, handle, contractAddress); -} - -export async function reencryptEuint16( - signers: Signers, - instances: FhevmInstance, - user: AccountName, - handle: bigint, - contractAddress: string, -): Promise { - verifyType(handle, EUINT16_T); - return reencryptHandle(signers, instances, user, handle, contractAddress); -} - -export async function reencryptEuint32( - signers: Signers, - instances: FhevmInstance, - user: AccountName, - handle: bigint, - contractAddress: string, -): Promise { - verifyType(handle, EUINT32_T); - return reencryptHandle(signers, instances, user, handle, contractAddress); -} - -export async function reencryptEuint64( - signers: Signers, - instances: FhevmInstance, - user: AccountName, - handle: bigint, - contractAddress: string, -): Promise { - verifyType(handle, EUINT64_T); - return reencryptHandle(signers, instances, user, handle, contractAddress); -} - -export async function reencryptEuint128( - signers: Signers, - instances: FhevmInstance, - user: AccountName, - handle: bigint, - contractAddress: string, -): Promise { - verifyType(handle, EUINT128_T); - return reencryptHandle(signers, instances, user, handle, contractAddress); -} - -export async function reencryptEaddress( - signers: Signers, - instances: FhevmInstance, - user: AccountName, - handle: bigint, - contractAddress: string, -): Promise { - verifyType(handle, EUINT160_T); - const addressAsUint160: bigint = await reencryptHandle(signers, instances, user, handle, contractAddress); - const handleStr = "0x" + addressAsUint160.toString(16).padStart(40, "0"); - return handleStr; -} - -export async function reencryptEuint256( - signers: Signers, - instances: FhevmInstance, - user: AccountName, - handle: bigint, - contractAddress: string, -): Promise { - verifyType(handle, EUINT256_T); - return reencryptHandle(signers, instances, user, handle, contractAddress); -} - -export async function reencryptEbytes64( - signers: Signers, - instances: FhevmInstance, - user: AccountName, - handle: bigint, - contractAddress: string, -): Promise { - verifyType(handle, EBYTES64_T); - return reencryptHandle(signers, instances, user, handle, contractAddress); -} - -export async function reencryptEbytes128( - signers: Signers, - instances: FhevmInstance, - user: AccountName, - handle: bigint, - contractAddress: string, -): Promise { - verifyType(handle, EBYTES128_T); - return reencryptHandle(signers, instances, user, handle, contractAddress); -} - -export async function reencryptEbytes256( - signers: Signers, - instances: FhevmInstance, - user: AccountName, - handle: bigint, - contractAddress: string, -): Promise { - verifyType(handle, EBYTES256_T); - return reencryptHandle(signers, instances, user, handle, contractAddress); -} - -/** - * @dev This function is to reencrypt handles. - * It does not verify types. - */ -async function reencryptHandle( - signers: Signers, - instance: FhevmInstance, - user: AccountName, - handle: bigint, - contractAddress: string, -): Promise { - const { publicKey: publicKey, privateKey: privateKey } = instance.generateKeypair(); - const eip712 = instance.createEIP712(publicKey, contractAddress); - const signature = await signers[user as keyof Signers].signTypedData( - eip712.domain, - { Reencrypt: eip712.types.Reencrypt }, - eip712.message, - ); - - const reencryptedHandle = await instance.reencrypt( - handle, - privateKey, - publicKey, - signature.replace("0x", ""), - contractAddress, - signers[user as keyof Signers].address, - ); - - return reencryptedHandle; -} diff --git a/contracts/test/signers.ts b/contracts/test/signers.ts deleted file mode 100644 index 77353df..0000000 --- a/contracts/test/signers.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { HardhatEthersSigner } from "@nomicfoundation/hardhat-ethers/signers"; -import { ethers } from "hardhat"; - -import { ACCOUNT_NAMES } from "./constants"; - -export type AccountNames = (typeof ACCOUNT_NAMES)[number]; - -export type Signers = { - [K in AccountNames]: HardhatEthersSigner; -}; - -const signers: Signers = {} as Signers; - -export const initSigners = async (): Promise => { - if (Object.entries(signers).length === 0) { - const eSigners = await ethers.getSigners(); - for (let index = 0; index < ACCOUNT_NAMES.length; index++) { - const name = ACCOUNT_NAMES[index] as keyof Signers; - signers[name] = eSigners[index]; - } - } -}; - -export const getSigners = async (): Promise => { - return signers; -}; diff --git a/contracts/test/utils.ts b/contracts/test/utils.ts deleted file mode 100644 index 39c5fb4..0000000 --- a/contracts/test/utils.ts +++ /dev/null @@ -1,317 +0,0 @@ -import { toBufferBE } from "bigint-buffer"; -import { ethers, network } from "hardhat"; - -import { awaitCoprocessor, getClearText } from "./coprocessorUtils"; - -export const mineNBlocks = async (n: number) => { - for (let index = 0; index < n; index++) { - await ethers.provider.send("evm_mine"); - } -}; - -export const bigIntToBytes64 = (value: bigint) => { - return new Uint8Array(toBufferBE(value, 64)); -}; - -export const bigIntToBytes128 = (value: bigint) => { - return new Uint8Array(toBufferBE(value, 128)); -}; - -export const bigIntToBytes256 = (value: bigint) => { - return new Uint8Array(toBufferBE(value, 256)); -}; - -export const waitNBlocks = async (Nblocks: number) => { - const currentBlock = await ethers.provider.getBlockNumber(); - if (network.name === "hardhat") { - await produceDummyTransactions(Nblocks); - } - await waitForBlock(currentBlock + Nblocks); -}; - -export const produceDummyTransactions = async (blockCount: number) => { - let counter = blockCount; - while (counter >= 0) { - counter--; - const [signer] = await ethers.getSigners(); - const nullAddress = "0x0000000000000000000000000000000000000000"; - const tx = { - to: nullAddress, - value: 0n, - }; - const receipt = await signer.sendTransaction(tx); - await receipt.wait(); - } -}; - -const waitForBlock = (blockNumber: bigint | number) => { - return new Promise((resolve, reject) => { - const waitBlock = async (currentBlock: number) => { - if (blockNumber <= BigInt(currentBlock)) { - await ethers.provider.off("block", waitBlock); - resolve(blockNumber); - } - }; - ethers.provider.on("block", waitBlock).catch((err) => { - reject(err); - }); - }); -}; - -const EBOOL_T = 0; -const EUINT4_T = 1; -const EUINT8_T = 2; -const EUINT16_T = 3; -const EUINT32_T = 4; -const EUINT64_T = 5; -const EUINT128_T = 6; -const EUINT160_T = 7; // @dev It is the one for eaddresses. -const EUINT256_T = 8; -const EBYTES64_T = 9; -const EBYTES128_T = 10; -const EBYTES256_T = 11; - -function verifyType(handle: bigint, expectedType: number) { - if (handle === 0n) { - throw "Handle is not initialized"; - } - if (handle.toString(2).length > 256) { - throw "Handle is not a bytes32"; - } - const typeCt = handle >> 8n; - if (Number(typeCt % 256n) !== expectedType) { - throw "Wrong encrypted type for the handle"; - } -} - -export const debug = { - /** - * @debug - * This function is intended for debugging purposes only. - * It cannot be used in production code, since it requires the FHE private key for decryption. - * In production, decryption is only possible via an asyncronous on-chain call to the Gateway. - * - * @param {bigint} a handle to decrypt - * @returns {bool} - */ - decryptBool: async (handle: bigint): Promise => { - verifyType(handle, EBOOL_T); - if (network.name === "hardhat") { - await awaitCoprocessor(); - return (await getClearText(handle)) === "1"; - } else { - throw Error("The debug.decryptBool function can only be called in mocked mode"); - } - }, - - /** - * @debug - * This function is intended for debugging purposes only. - * It cannot be used in production code, since it requires the FHE private key for decryption. - * In production, decryption is only possible via an asyncronous on-chain call to the Gateway. - * - * @param {bigint} handle to decrypt - * @returns {bigint} - */ - decrypt4: async (handle: bigint): Promise => { - verifyType(handle, EUINT4_T); - if (network.name === "hardhat") { - await awaitCoprocessor(); - return BigInt(await getClearText(handle)); - } else { - throw Error("The debug.decrypt4 function can only be called in mocked mode"); - } - }, - - /** - * @debug - * This function is intended for debugging purposes only. - * It cannot be used in production code, since it requires the FHE private key for decryption. - * In production, decryption is only possible via an asyncronous on-chain call to the Gateway. - * - * @param {bigint} a handle to decrypt - * @returns {bigint} - */ - decrypt8: async (handle: bigint): Promise => { - verifyType(handle, EUINT8_T); - if (network.name === "hardhat") { - await awaitCoprocessor(); - return BigInt(await getClearText(handle)); - } else { - throw Error("The debug.decrypt8 function can only be called in mocked mode"); - } - }, - - /** - * @debug - * This function is intended for debugging purposes only. - * It cannot be used in production code, since it requires the FHE private key for decryption. - * In production, decryption is only possible via an asyncronous on-chain call to the Gateway. - * - * @param {bigint} handle to decrypt - * @returns {bigint} - */ - decrypt16: async (handle: bigint): Promise => { - verifyType(handle, EUINT16_T); - if (network.name === "hardhat") { - await awaitCoprocessor(); - return BigInt(await getClearText(handle)); - } else { - throw Error("The debug.decrypt16 function can only be called in mocked mode"); - } - }, - - /** - * @debug - * This function is intended for debugging purposes only. - * It cannot be used in production code, since it requires the FHE private key for decryption. - * In production, decryption is only possible via an asyncronous on-chain call to the Gateway. - * - * @param {bigint} handle to decrypt - * @returns {bigint} - */ - decrypt32: async (handle: bigint): Promise => { - verifyType(handle, EUINT32_T); - if (network.name === "hardhat") { - await awaitCoprocessor(); - return BigInt(await getClearText(handle)); - } else { - throw Error("The debug.decrypt32 function can only be called in mocked mode"); - } - }, - - /** - * @debug - * This function is intended for debugging purposes only. - * It cannot be used in production code, since it requires the FHE private key for decryption. - * In production, decryption is only possible via an asyncronous on-chain call to the Gateway. - * - * @param {bigint} handle to decrypt - * @returns {bigint} - */ - decrypt64: async (handle: bigint): Promise => { - verifyType(handle, EUINT64_T); - if (network.name === "hardhat") { - await awaitCoprocessor(); - return BigInt(await getClearText(handle)); - } else { - throw Error("The debug.decrypt64 function can only be called in mocked mode"); - } - }, - - /** - * @debug - * This function is intended for debugging purposes only. - * It cannot be used in production code, since it requires the FHE private key for decryption. - * In production, decryption is only possible via an asyncronous on-chain call to the Gateway. - * - * @param {bigint} handle to decrypt - * @returns {bigint} - */ - decrypt128: async (handle: bigint): Promise => { - verifyType(handle, EUINT128_T); - if (network.name === "hardhat") { - await awaitCoprocessor(); - return BigInt(await getClearText(handle)); - } else { - throw Error("The debug.decrypt128 function can only be called in mocked mode"); - } - }, - - /** - * @debug - * This function is intended for debugging purposes only. - * It cannot be used in production code, since it requires the FHE private key for decryption. - * In production, decryption is only possible via an asyncronous on-chain call to the Gateway. - * - * @param {bigint} handle to decrypt - * @returns {bigint} - */ - decrypt256: async (handle: bigint): Promise => { - verifyType(handle, EUINT256_T); - if (network.name === "hardhat") { - await awaitCoprocessor(); - return BigInt(await getClearText(handle)); - } else { - throw Error("The debug.decrypt256 function can only be called in mocked mode"); - } - }, - - /** - * @debug - * This function is intended for debugging purposes only. - * It cannot be used in production code, since it requires the FHE private key for decryption. - * In production, decryption is only possible via an asyncronous on-chain call to the Gateway. - * - * @param {bigint} handle to decrypt - * @returns {string} - */ - decryptAddress: async (handle: bigint): Promise => { - verifyType(handle, EUINT160_T); - if (network.name === "hardhat") { - await awaitCoprocessor(); - const bigintAdd = BigInt(await getClearText(handle)); - const handleStr = "0x" + bigintAdd.toString(16).padStart(40, "0"); - return handleStr; - } else { - throw Error("The debug.decryptAddress function can only be called in mocked mode"); - } - }, - - /** - * @debug - * This function is intended for debugging purposes only. - * It cannot be used in production code, since it requires the FHE private key for decryption. - * In production, decryption is only possible via an asyncronous on-chain call to the Gateway. - * - * @param {bigint} a handle to decrypt - * @returns {bigint} - */ - decryptEbytes64: async (handle: bigint): Promise => { - verifyType(handle, EBYTES64_T); - if (network.name === "hardhat") { - await awaitCoprocessor(); - return ethers.toBeHex(await getClearText(handle), 64); - } else { - throw Error("The debug.decryptEbytes64 function can only be called in mocked mode"); - } - }, - - /** - * @debug - * This function is intended for debugging purposes only. - * It cannot be used in production code, since it requires the FHE private key for decryption. - * In production, decryption is only possible via an asyncronous on-chain call to the Gateway. - * - * @param {bigint} handle to decrypt - * @returns {bigint} - */ - decryptEbytes128: async (handle: bigint): Promise => { - verifyType(handle, EBYTES128_T); - if (network.name === "hardhat") { - await awaitCoprocessor(); - return ethers.toBeHex(await getClearText(handle), 128); - } else { - throw Error("The debug.decryptEbytes128 function can only be called in mocked mode"); - } - }, - - /** - * @debug - * This function is intended for debugging purposes only. - * It cannot be used in production code, since it requires the FHE private key for decryption. - * In production, decryption is only possible via an asyncronous on-chain call to the Gateway. - * - * @param {bigint} handle to decrypt - * @returns {bigint} - */ - decryptEbytes256: async (handle: bigint): Promise => { - verifyType(handle, EBYTES256_T); - if (network.name === "hardhat") { - await awaitCoprocessor(); - return ethers.toBeHex(await getClearText(handle), 256); - } else { - throw Error("The debug.decryptEbytes256 function can only be called in mocked mode"); - } - }, -}; diff --git a/contracts/tsconfig.json b/contracts/tsconfig.json deleted file mode 100644 index d6cca4d..0000000 --- a/contracts/tsconfig.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "compilerOptions": { - "declaration": true, - "declarationMap": true, - "emitDecoratorMetadata": true, - "esModuleInterop": true, - "experimentalDecorators": true, - "forceConsistentCasingInFileNames": true, - "lib": ["es2020", "dom"], - "module": "commonjs", - "moduleResolution": "node", - "noImplicitAny": true, - "removeComments": true, - "resolveJsonModule": true, - "sourceMap": true, - "strict": true, - "target": "es2020", - "types": ["jest", "node"] - }, - "exclude": ["node_modules"], - "files": ["./hardhat.config.ts"], - "include": ["src/**/*", "tasks/**/*", "test/**/*", "deploy/**/*", "types/"] -} diff --git a/frontend/.eslintrc.json b/frontend-visual/.eslintrc.json similarity index 100% rename from frontend/.eslintrc.json rename to frontend-visual/.eslintrc.json diff --git a/frontend-visual/.gitignore b/frontend-visual/.gitignore new file mode 100644 index 0000000..fd3dbb5 --- /dev/null +++ b/frontend-visual/.gitignore @@ -0,0 +1,36 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js +.yarn/install-state.gz + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# local env files +.env*.local + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts diff --git a/frontend-visual/README.md b/frontend-visual/README.md new file mode 100644 index 0000000..6c869b7 --- /dev/null +++ b/frontend-visual/README.md @@ -0,0 +1,38 @@ +# dAppZAMA + +This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). + +## Getting Started + +First, run the development server: + +```bash +npm run dev +# or +yarn dev +# or +pnpm dev +# or +bun dev +``` + +Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. + +You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. + +This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. + +## Learn More + +To learn more about Next.js, take a look at the following resources: + +- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. +- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. + +You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! + +## Deploy on Vercel + +The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. + +Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. diff --git a/frontend/app/dapps/[slug]/page.tsx b/frontend-visual/app/dapps/[slug]/page.tsx similarity index 100% rename from frontend/app/dapps/[slug]/page.tsx rename to frontend-visual/app/dapps/[slug]/page.tsx diff --git a/frontend/app/favicon.ico b/frontend-visual/app/favicon.ico similarity index 100% rename from frontend/app/favicon.ico rename to frontend-visual/app/favicon.ico diff --git a/frontend/app/fonts/Telegraf UltraBold 800.woff b/frontend-visual/app/fonts/Telegraf UltraBold 800.woff similarity index 100% rename from frontend/app/fonts/Telegraf UltraBold 800.woff rename to frontend-visual/app/fonts/Telegraf UltraBold 800.woff diff --git a/frontend/app/fonts/Telegraf UltraLight 200.woff b/frontend-visual/app/fonts/Telegraf UltraLight 200.woff similarity index 100% rename from frontend/app/fonts/Telegraf UltraLight 200.woff rename to frontend-visual/app/fonts/Telegraf UltraLight 200.woff diff --git a/frontend/app/fonts/TelegrafRegular_272984568a25d8528fe2de8b20b29011.woff b/frontend-visual/app/fonts/TelegrafRegular_272984568a25d8528fe2de8b20b29011.woff similarity index 100% rename from frontend/app/fonts/TelegrafRegular_272984568a25d8528fe2de8b20b29011.woff rename to frontend-visual/app/fonts/TelegrafRegular_272984568a25d8528fe2de8b20b29011.woff diff --git a/frontend/app/globals.css b/frontend-visual/app/globals.css similarity index 100% rename from frontend/app/globals.css rename to frontend-visual/app/globals.css diff --git a/frontend/app/layout.tsx b/frontend-visual/app/layout.tsx similarity index 100% rename from frontend/app/layout.tsx rename to frontend-visual/app/layout.tsx diff --git a/frontend/app/page.tsx b/frontend-visual/app/page.tsx similarity index 100% rename from frontend/app/page.tsx rename to frontend-visual/app/page.tsx diff --git a/frontend/components.json b/frontend-visual/components.json similarity index 100% rename from frontend/components.json rename to frontend-visual/components.json diff --git a/frontend/components/ConnectButton.tsx b/frontend-visual/components/ConnectButton.tsx similarity index 100% rename from frontend/components/ConnectButton.tsx rename to frontend-visual/components/ConnectButton.tsx diff --git a/frontend/components/DAppCard.tsx b/frontend-visual/components/DAppCard.tsx similarity index 100% rename from frontend/components/DAppCard.tsx rename to frontend-visual/components/DAppCard.tsx diff --git a/frontend/components/Header.tsx b/frontend-visual/components/Header.tsx similarity index 100% rename from frontend/components/Header.tsx rename to frontend-visual/components/Header.tsx diff --git a/frontend/components/ui/button.tsx b/frontend-visual/components/ui/button.tsx similarity index 100% rename from frontend/components/ui/button.tsx rename to frontend-visual/components/ui/button.tsx diff --git a/frontend/components/ui/dropdown-menu.tsx b/frontend-visual/components/ui/dropdown-menu.tsx similarity index 100% rename from frontend/components/ui/dropdown-menu.tsx rename to frontend-visual/components/ui/dropdown-menu.tsx diff --git a/frontend/lib/utils.ts b/frontend-visual/lib/utils.ts similarity index 100% rename from frontend/lib/utils.ts rename to frontend-visual/lib/utils.ts diff --git a/frontend/next.config.mjs b/frontend-visual/next.config.mjs similarity index 100% rename from frontend/next.config.mjs rename to frontend-visual/next.config.mjs diff --git a/frontend-visual/package-lock.json b/frontend-visual/package-lock.json new file mode 100644 index 0000000..c3f5e21 --- /dev/null +++ b/frontend-visual/package-lock.json @@ -0,0 +1,5188 @@ +{ + "name": "my-app", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "my-app", + "version": "0.1.0", + "dependencies": { + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "lucide-react": "^0.462.0", + "next": "14.2.16", + "react": "^18", + "react-dom": "^18", + "tailwind-merge": "^2.5.5", + "tailwindcss-animate": "^1.0.7" + }, + "devDependencies": { + "@types/node": "^20", + "@types/react": "^18", + "@types/react-dom": "^18", + "eslint": "^8", + "eslint-config-next": "14.2.16", + "postcss": "^8", + "tailwindcss": "^3.4.1", + "typescript": "^5" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", + "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@next/env": { + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.16.tgz", + "integrity": "sha512-fLrX5TfJzHCbnZ9YUSnGW63tMV3L4nSfhgOQ0iCcX21Pt+VSTDuaLsSuL8J/2XAiVA5AnzvXDpf6pMs60QxOag==", + "license": "MIT" + }, + "node_modules/@next/eslint-plugin-next": { + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-14.2.16.tgz", + "integrity": "sha512-noORwKUMkKc96MWjTOwrsUCjky0oFegHbeJ1yEnQBGbMHAaTEIgLZIIfsYF0x3a06PiS+2TXppfifR+O6VWslg==", + "dev": true, + "license": "MIT", + "dependencies": { + "glob": "10.3.10" + } + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.16.tgz", + "integrity": "sha512-uFT34QojYkf0+nn6MEZ4gIWQ5aqGF11uIZ1HSxG+cSbj+Mg3+tYm8qXYd3dKN5jqKUm5rBVvf1PBRO/MeQ6rxw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-14.2.16.tgz", + "integrity": "sha512-mCecsFkYezem0QiZlg2bau3Xul77VxUD38b/auAjohMA22G9KTJneUYMv78vWoCCFkleFAhY1NIvbyjj1ncG9g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.2.16.tgz", + "integrity": "sha512-yhkNA36+ECTC91KSyZcgWgKrYIyDnXZj8PqtJ+c2pMvj45xf7y/HrgI17hLdrcYamLfVt7pBaJUMxADtPaczHA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.2.16.tgz", + "integrity": "sha512-X2YSyu5RMys8R2lA0yLMCOCtqFOoLxrq2YbazFvcPOE4i/isubYjkh+JCpRmqYfEuCVltvlo+oGfj/b5T2pKUA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.2.16.tgz", + "integrity": "sha512-9AGcX7VAkGbc5zTSa+bjQ757tkjr6C/pKS7OK8cX7QEiK6MHIIezBLcQ7gQqbDW2k5yaqba2aDtaBeyyZh1i6Q==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.2.16.tgz", + "integrity": "sha512-Klgeagrdun4WWDaOizdbtIIm8khUDQJ/5cRzdpXHfkbY91LxBXeejL4kbZBrpR/nmgRrQvmz4l3OtttNVkz2Sg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.2.16.tgz", + "integrity": "sha512-PwW8A1UC1Y0xIm83G3yFGPiOBftJK4zukTmk7DI1CebyMOoaVpd8aSy7K6GhobzhkjYvqS/QmzcfsWG2Dwizdg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-ia32-msvc": { + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.2.16.tgz", + "integrity": "sha512-jhPl3nN0oKEshJBNDAo0etGMzv0j3q3VYorTSFqH1o3rwv1MQRdor27u1zhkgsHPNeY1jxcgyx1ZsCkDD1IHgg==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.2.16.tgz", + "integrity": "sha512-OA7NtfxgirCjfqt+02BqxC3MIgM/JaGjw9tOe4fyZgPsqfseNiMPnCRP44Pfs+Gpo9zPN+SXaFsgP6vk8d571A==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nolyfill/is-core-module": { + "version": "1.0.39", + "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", + "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.4.0" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rushstack/eslint-patch": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.4.tgz", + "integrity": "sha512-WJgX9nzTqknM393q1QJDJmoW28kUfEnybeTfVNcNAPnIx210RXm2DiXiHzfNPJNIUUb1tJnz/l4QGtJ30PgWmA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@swc/counter": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.3.tgz", + "integrity": "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ==", + "license": "Apache-2.0" + }, + "node_modules/@swc/helpers": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.5.tgz", + "integrity": "sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==", + "license": "Apache-2.0", + "dependencies": { + "@swc/counter": "^0.1.3", + "tslib": "^2.4.0" + } + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "20.17.8", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.8.tgz", + "integrity": "sha512-ahz2g6/oqbKalW9sPv6L2iRbhLnojxjYWspAqhjvqSWBgGebEJT5GvRmk0QXPj3sbC6rU0GTQjPLQkmR8CObvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.2" + } + }, + "node_modules/@types/prop-types": { + "version": "15.7.13", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz", + "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "18.3.12", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz", + "integrity": "sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.16.0.tgz", + "integrity": "sha512-5YTHKV8MYlyMI6BaEG7crQ9BhSc8RxzshOReKwZwRWN0+XvvTOm+L/UYLCYxFpfwYuAAqhxiq4yae0CMFwbL7Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.16.0", + "@typescript-eslint/type-utils": "8.16.0", + "@typescript-eslint/utils": "8.16.0", + "@typescript-eslint/visitor-keys": "8.16.0", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.16.0.tgz", + "integrity": "sha512-D7DbgGFtsqIPIFMPJwCad9Gfi/hC0PWErRRHFnaCWoEDYi5tQUDiJCTmGUbBiLzjqAck4KcXt9Ayj0CNlIrF+w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/scope-manager": "8.16.0", + "@typescript-eslint/types": "8.16.0", + "@typescript-eslint/typescript-estree": "8.16.0", + "@typescript-eslint/visitor-keys": "8.16.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.16.0.tgz", + "integrity": "sha512-mwsZWubQvBki2t5565uxF0EYvG+FwdFb8bMtDuGQLdCCnGPrDEDvm1gtfynuKlnpzeBRqdFCkMf9jg1fnAK8sg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.16.0", + "@typescript-eslint/visitor-keys": "8.16.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.16.0.tgz", + "integrity": "sha512-IqZHGG+g1XCWX9NyqnI/0CX5LL8/18awQqmkZSl2ynn8F76j579dByc0jhfVSnSnhf7zv76mKBQv9HQFKvDCgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "8.16.0", + "@typescript-eslint/utils": "8.16.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.16.0.tgz", + "integrity": "sha512-NzrHj6thBAOSE4d9bsuRNMvk+BvaQvmY4dDglgkgGC0EW/tB3Kelnp3tAKH87GEwzoxgeQn9fNGRyFJM/xd+GQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.16.0.tgz", + "integrity": "sha512-E2+9IzzXMc1iaBy9zmo+UYvluE3TW7bCGWSF41hVWUE01o8nzr1rvOQYSxelxr6StUvRcTMe633eY8mXASMaNw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "8.16.0", + "@typescript-eslint/visitor-keys": "8.16.0", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.16.0.tgz", + "integrity": "sha512-C1zRy/mOL8Pj157GiX4kaw7iyRLKfJXBR3L82hk5kS/GyHcOFmy4YUq/zfZti72I9wnuQtA/+xzft4wCC8PJdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.16.0", + "@typescript-eslint/types": "8.16.0", + "@typescript-eslint/typescript-estree": "8.16.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.16.0.tgz", + "integrity": "sha512-pq19gbaMOmFE3CbL0ZB8J8BFCo2ckfHBfaIsaOZgBIF4EoISJIdLX5xRhd0FGB0LlHReNRuzoJoMGpTjq8F2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.16.0", + "eslint-visitor-keys": "^4.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz", + "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/acorn": { + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", + "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "license": "MIT" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "license": "MIT" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axe-core": { + "version": "4.10.2", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.10.2.tgz", + "integrity": "sha512-RE3mdQ7P3FRSe7eqCWoeQ/Z9QXrtniSjp1wUjt5nRC3WIpz5rSCve6o3fsZ2aCpJtrZjSZgjwXAoTO5k4tEI0w==", + "dev": true, + "license": "MPL-2.0", + "engines": { + "node": ">=4" + } + }, + "node_modules/axobject-query": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001684", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001684.tgz", + "integrity": "sha512-G1LRwLIQjBQoyq0ZJGqGIJUXzJ8irpbjHLpVRXDvBEScFJ9b17sgK6vlx0GAJFE21okD7zXl08rRRUfq6HdoEQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/class-variance-authority": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz", + "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==", + "license": "Apache-2.0", + "dependencies": { + "clsx": "^2.1.1" + }, + "funding": { + "url": "https://polar.sh/cva" + } + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "license": "MIT" + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "dev": true, + "license": "MIT" + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "license": "Apache-2.0" + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "license": "MIT" + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "license": "MIT" + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT" + }, + "node_modules/enhanced-resolve": { + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/es-abstract": { + "version": "1.23.5", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.5.tgz", + "integrity": "sha512-vlmniQ0WNPwXqA0BnmwV3Ng7HxiGlh6r5U6JcTMNx8OilcAGqVJBHJcPjqOMaczU9fRuRK5Px2BdVyPRnKMMVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.3", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.0.tgz", + "integrity": "sha512-tpxqxncxnpw3c93u8n3VOzACmRFoVmWJqbWXvX/JfKbkhBw1oslgPrUfeSt2psuqyEJFD6N/9lg5i7bsKpoq+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "globalthis": "^1.0.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "iterator.prototype": "^1.1.3", + "safe-array-concat": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.0" + } + }, + "node_modules/es-to-primitive": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-next": { + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-14.2.16.tgz", + "integrity": "sha512-HOcnCJsyLXR7B8wmjaCgkTSpz+ijgOyAkP8OlvANvciP8PspBYFEBTmakNMxOf71fY0aKOm/blFIiKnrM4K03Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@next/eslint-plugin-next": "14.2.16", + "@rushstack/eslint-patch": "^1.3.3", + "@typescript-eslint/eslint-plugin": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "eslint-import-resolver-node": "^0.3.6", + "eslint-import-resolver-typescript": "^3.5.2", + "eslint-plugin-import": "^2.28.1", + "eslint-plugin-jsx-a11y": "^6.7.1", + "eslint-plugin-react": "^7.33.2", + "eslint-plugin-react-hooks": "^4.5.0 || 5.0.0-canary-7118f5dd7-20230705" + }, + "peerDependencies": { + "eslint": "^7.23.0 || ^8.0.0", + "typescript": ">=3.3.1" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-typescript": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.3.tgz", + "integrity": "sha512-ud9aw4szY9cCT1EWWdGv1L1XR6hh2PaRWif0j2QjQ0pgTY/69iw+W0Z4qZv5wHahOl8isEr+k/JnyAqNQkLkIA==", + "dev": true, + "license": "ISC", + "dependencies": { + "@nolyfill/is-core-module": "1.0.39", + "debug": "^4.3.5", + "enhanced-resolve": "^5.15.0", + "eslint-module-utils": "^2.8.1", + "fast-glob": "^3.3.2", + "get-tsconfig": "^4.7.5", + "is-bun-module": "^1.0.2", + "is-glob": "^4.0.3" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*", + "eslint-plugin-import-x": "*" + }, + "peerDependenciesMeta": { + "eslint-plugin-import": { + "optional": true + }, + "eslint-plugin-import-x": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz", + "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.31.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz", + "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.8", + "array.prototype.findlastindex": "^1.2.5", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.0", + "hasown": "^2.0.2", + "is-core-module": "^2.15.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.0", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.8", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz", + "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "aria-query": "^5.3.2", + "array-includes": "^3.1.8", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "^4.10.0", + "axobject-query": "^4.1.0", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "hasown": "^2.0.2", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "safe-regex-test": "^1.0.3", + "string.prototype.includes": "^2.0.1" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.37.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.2.tgz", + "integrity": "sha512-EsTAnj9fLVr/GZleBLFbj/sSuXeWmp1eXIN60ceYnZveqEaUCyW4X+Vh4WTdUhCkW4xutXYqTXCUSyqD4rB75w==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.2", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.1.0", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.8", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.0", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.11", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "5.0.0-canary-7118f5dd7-20230705", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.0.0-canary-7118f5dd7-20230705.tgz", + "integrity": "sha512-AZYbMo/NW9chdL7vk6HQzQhT+PvTAEVqWk9ziruUoW2kAOcN5qNyelv70e0F1VNQAbvutOC9oc+xfWycI9FxDw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", + "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==", + "dev": true, + "license": "ISC" + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.1.tgz", + "integrity": "sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-async-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bun-module": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-1.3.0.tgz", + "integrity": "sha512-DgXeu5UWI0IsMQundYb5UAOzm6G2eVnarJ0byP6Tm55iZNKceD59LNPA2L4VvsScTtHcw0yEkVwSf7PC+QoLSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.6.3" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.0.tgz", + "integrity": "sha512-qfMdqbAQEwBw78ZyReKnlA8ezmPdb9BemzIIip/JkjaZUhitfXDkkr+3QTboW0JrSXT1QWyYShpvnNHGZ4c4yA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", + "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/iterator.prototype": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.3.tgz", + "integrity": "sha512-FW5iMbeQ6rBGm/oKgzq2aW4KvAGpxPzYES8N4g4xNXUKpL1mclMvOe+76AcLDTvD+Ze+sOpVhgdAQEKF4L9iGQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "reflect.getprototypeof": "^1.0.4", + "set-function-name": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jiti": { + "version": "1.21.6", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", + "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", + "license": "MIT", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/language-subtag-registry": { + "version": "0.3.23", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/language-tags": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "dev": true, + "license": "MIT", + "dependencies": { + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "license": "ISC" + }, + "node_modules/lucide-react": { + "version": "0.462.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.462.0.tgz", + "integrity": "sha512-NTL7EbAao9IFtuSivSZgrAh4fZd09Lr+6MTkqIxuHaH2nnYiYIzXPo06cOxHg9wKLdj6LL8TByG4qpePqwgx/g==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/next": { + "version": "14.2.16", + "resolved": "https://registry.npmjs.org/next/-/next-14.2.16.tgz", + "integrity": "sha512-LcO7WnFu6lYSvCzZoo1dB+IO0xXz5uEv52HF1IUN0IqVTUIZGHuuR10I5efiLadGt+4oZqTcNZyVVEem/TM5nA==", + "license": "MIT", + "dependencies": { + "@next/env": "14.2.16", + "@swc/helpers": "0.5.5", + "busboy": "1.6.0", + "caniuse-lite": "^1.0.30001579", + "graceful-fs": "^4.2.11", + "postcss": "8.4.31", + "styled-jsx": "5.1.1" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": ">=18.17.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "14.2.16", + "@next/swc-darwin-x64": "14.2.16", + "@next/swc-linux-arm64-gnu": "14.2.16", + "@next/swc-linux-arm64-musl": "14.2.16", + "@next/swc-linux-x64-gnu": "14.2.16", + "@next/swc-linux-x64-musl": "14.2.16", + "@next/swc-win32-arm64-msvc": "14.2.16", + "@next/swc-win32-ia32-msvc": "14.2.16", + "@next/swc-win32-x64-msvc": "14.2.16" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.41.2", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/next/node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/object-inspect": { + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", + "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", + "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.4.49", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", + "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "license": "MIT", + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/postcss-load-config/node_modules/lilconfig": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "license": "MIT" + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "license": "MIT", + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.7.tgz", + "integrity": "sha512-bMvFGIUKlc/eSfXNX+aZ+EL95/EgZzuwA0OBPTbZZDEJw/0AkentjMuM1oiRfwHrshqk4RzdgiTg5CcDalXN5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "which-builtin-type": "^1.1.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz", + "integrity": "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "license": "MIT", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-regex": "^1.1.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/string.prototype.includes": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", + "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz", + "integrity": "sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.7", + "regexp.prototype.flags": "^1.5.2", + "set-function-name": "^2.0.2", + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/styled-jsx": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.1.tgz", + "integrity": "sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==", + "license": "MIT", + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tailwind-merge": { + "version": "2.5.5", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.5.5.tgz", + "integrity": "sha512-0LXunzzAZzo0tEPxV3I297ffKZPlKDrjj7NXphC8V5ak9yHC5zRmxnOe2m/Rd/7ivsOMJe3JZ2JVocoDdQTRBA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, + "node_modules/tailwindcss": { + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.15.tgz", + "integrity": "sha512-r4MeXnfBmSOuKUWmXe6h2CcyfzJCEk4F0pptO5jlnYSIViUkVmsawj80N5h2lO3gwcmSb4n3PuN+e+GC1Guylw==", + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.6.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.2", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.6", + "lilconfig": "^2.1.0", + "micromatch": "^4.0.8", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.2", + "postcss-nested": "^6.2.0", + "postcss-selector-parser": "^6.1.2", + "resolve": "^1.22.8", + "sucrase": "^3.35.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tailwindcss-animate": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz", + "integrity": "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==", + "license": "MIT", + "peerDependencies": { + "tailwindcss": ">=3.0.0 || insiders" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "license": "MIT", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-api-utils": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.2.tgz", + "integrity": "sha512-ZF5gQIQa/UmzfvxbHZI3JXN0/Jt+vnAfAviNRAMc491laiK6YCLpCW9ft8oaCRFOTxCZtUTE6XB0ZQAe3olntw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "license": "Apache-2.0" + }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.3.tgz", + "integrity": "sha512-GsvTyUHTriq6o/bHcTd0vM7OQ9JEdlvluu9YISaA7+KzDzPaIzEeDFNkTfhdE3MYcNhNi0vq/LlegYgIs5yPAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "reflect.getprototypeof": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", + "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/undici-types": { + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true, + "license": "MIT" + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.0.tgz", + "integrity": "sha512-I+qLGQ/vucCby4tf5HsLmGueEla4ZhwTBSqaooS+Y0BuxN4Cp+okmGuV+8mXZ84KDI9BA+oklo+RzKg0ONdSUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.0.5", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.1.4", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.15" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/yaml": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.1.tgz", + "integrity": "sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/frontend-visual/package.json b/frontend-visual/package.json new file mode 100644 index 0000000..e7c63ad --- /dev/null +++ b/frontend-visual/package.json @@ -0,0 +1,34 @@ +{ + "name": "my-app", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "next lint" + }, + "dependencies": { + "@radix-ui/react-dropdown-menu": "^2.1.2", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "ethers": "^6.13.4", + "lucide-react": "^0.462.0", + "next": "14.2.16", + "radix-ui": "link:radix-ui", + "react": "^18", + "react-dom": "^18", + "tailwind-merge": "^2.5.5", + "tailwindcss-animate": "^1.0.7" + }, + "devDependencies": { + "@types/node": "^20", + "@types/react": "^18", + "@types/react-dom": "^18", + "eslint": "^8", + "eslint-config-next": "14.2.16", + "postcss": "^8", + "tailwindcss": "^3.4.1", + "typescript": "^5" + } +} diff --git a/frontend/pnpm-lock.yaml b/frontend-visual/pnpm-lock.yaml similarity index 100% rename from frontend/pnpm-lock.yaml rename to frontend-visual/pnpm-lock.yaml diff --git a/frontend/postcss.config.mjs b/frontend-visual/postcss.config.mjs similarity index 100% rename from frontend/postcss.config.mjs rename to frontend-visual/postcss.config.mjs diff --git a/frontend/public/fonts/Telegraf UltraBold 800.woff b/frontend-visual/public/fonts/Telegraf UltraBold 800.woff similarity index 100% rename from frontend/public/fonts/Telegraf UltraBold 800.woff rename to frontend-visual/public/fonts/Telegraf UltraBold 800.woff diff --git a/frontend/public/fonts/Telegraf UltraLight 200.woff b/frontend-visual/public/fonts/Telegraf UltraLight 200.woff similarity index 100% rename from frontend/public/fonts/Telegraf UltraLight 200.woff rename to frontend-visual/public/fonts/Telegraf UltraLight 200.woff diff --git a/frontend/public/fonts/TelegrafRegular_272984568a25d8528fe2de8b20b29011.woff b/frontend-visual/public/fonts/TelegrafRegular_272984568a25d8528fe2de8b20b29011.woff similarity index 100% rename from frontend/public/fonts/TelegrafRegular_272984568a25d8528fe2de8b20b29011.woff rename to frontend-visual/public/fonts/TelegrafRegular_272984568a25d8528fe2de8b20b29011.woff diff --git a/frontend/public/test.png b/frontend-visual/public/test.png similarity index 100% rename from frontend/public/test.png rename to frontend-visual/public/test.png diff --git a/frontend/tailwind.config.ts b/frontend-visual/tailwind.config.ts similarity index 100% rename from frontend/tailwind.config.ts rename to frontend-visual/tailwind.config.ts diff --git a/frontend-visual/tsconfig.json b/frontend-visual/tsconfig.json new file mode 100644 index 0000000..e7ff90f --- /dev/null +++ b/frontend-visual/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": ["./*"] + } + }, + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "exclude": ["node_modules"] +} diff --git a/frontend/.env.example b/frontend/.env.example new file mode 100644 index 0000000..dc25827 --- /dev/null +++ b/frontend/.env.example @@ -0,0 +1,3 @@ +VITE_ACL_ADDRESS=0xFee8407e2f5e3Ee68ad77cAE98c434e637f516e5 +VITE_KMS_ADDRESS=0x9D6891A6240D6130c54ae243d8005063D05fE14b +VITE_GATEWAY_URL=https://gateway.sepolia.zama.ai/ \ No newline at end of file diff --git a/frontend/.eslintrc.cjs b/frontend/.eslintrc.cjs new file mode 100644 index 0000000..be2d504 --- /dev/null +++ b/frontend/.eslintrc.cjs @@ -0,0 +1,30 @@ +/* eslint-env node */ + +module.exports = { + root: true, + env: { browser: true, es2020: true }, + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:@typescript-eslint/recommended-requiring-type-checking', + 'plugin:react-hooks/recommended', + ], + parser: '@typescript-eslint/parser', + parserOptions: { + ecmaVersion: 'latest', + sourceType: 'module', + project: true, + tsconfigRootDir: __dirname, + }, + plugins: ['react-refresh'], + rules: { + 'react-refresh/only-export-components': ['warn', { allowConstantExport: true }], + '@typescript-eslint/no-unsafe-call': 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-non-null-assertion': 'off', + '@typescript-eslint/no-unsafe-assignment': 'off', + '@typescript-eslint/no-unsafe-member-access': 'off', + '@typescript-eslint/no-misused-promises': 'off', + }, + ignorePatterns: ['.eslintrc.cjs'], +}; diff --git a/frontend/.gitignore b/frontend/.gitignore index fd3dbb5..1cac559 100644 --- a/frontend/.gitignore +++ b/frontend/.gitignore @@ -1,36 +1,25 @@ -# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. - -# dependencies -/node_modules -/.pnp -.pnp.js -.yarn/install-state.gz - -# testing -/coverage - -# next.js -/.next/ -/out/ - -# production -/build - -# misc -.DS_Store -*.pem - -# debug +# Logs +logs +*.log npm-debug.log* yarn-debug.log* yarn-error.log* - -# local env files -.env*.local - -# vercel -.vercel - -# typescript -*.tsbuildinfo -next-env.d.ts +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? +.env \ No newline at end of file diff --git a/frontend/.prettierrc b/frontend/.prettierrc new file mode 100644 index 0000000..544138b --- /dev/null +++ b/frontend/.prettierrc @@ -0,0 +1,3 @@ +{ + "singleQuote": true +} diff --git a/frontend/LICENSE b/frontend/LICENSE new file mode 100644 index 0000000..daa03f9 --- /dev/null +++ b/frontend/LICENSE @@ -0,0 +1,28 @@ +BSD 3-Clause License + +Copyright (c) 2023, Zama + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/frontend/README.md b/frontend/README.md index 6c869b7..a9c0e35 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -1,38 +1,33 @@ -# dAppZAMA +# fhevmjs-react-template -This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). +This is a simple template to show how to use fhevmjs with Vite + React. -## Getting Started - -First, run the development server: +## Getting started ```bash -npm run dev -# or -yarn dev -# or -pnpm dev -# or -bun dev +npm install ``` -Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. +## Configuration -You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. +Copy `.env.example` to `.env` and update the gateway URL, ACL address, and KMS address to match the fhEVM you're using. -This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. +## Development -## Learn More +```bash +npm run dev +``` -To learn more about Next.js, take a look at the following resources: +The server listens on [http://localhost:4173/](http://localhost:4173/) -- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. -- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. +Note: HMR is currently broken because Vite does not handle WASM correctly. A workaround has been implemented as a script: running `npm run dev` will execute a build watch alongside Vite preview. If you have a solution for enabling the Vite dev server with HMR, feel free to open a pull request! :) -You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! +## Build -## Deploy on Vercel +```bash +npm run build +``` -The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. +## Documentation -Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details. +For more information about fhevmjs, you can [read the documentation](https://docs.zama.ai/fhevm). diff --git a/frontend/index.html b/frontend/index.html new file mode 100644 index 0000000..23c73c1 --- /dev/null +++ b/frontend/index.html @@ -0,0 +1,13 @@ + + + + + + + fhEVM React demo + + +
+ + + diff --git a/frontend/package-lock.json b/frontend/package-lock.json new file mode 100644 index 0000000..ea2cd2f --- /dev/null +++ b/frontend/package-lock.json @@ -0,0 +1,8458 @@ +{ + "name": "fhevmjs-react-template", + "version": "0.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "fhevmjs-react-template", + "version": "0.0.0", + "dependencies": { + "ethers": "^6.6.4", + "idb": "^8.0.0", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "web3-validator": "^2.0.6" + }, + "devDependencies": { + "@types/react": "^18.3.1", + "@types/react-dom": "^18.3.0", + "@typescript-eslint/eslint-plugin": "^7.13.1", + "@typescript-eslint/parser": "^7.13.1", + "@vitejs/plugin-react": "^4.3.4", + "bigint-buffer": "^1.1.5", + "eslint": "^8.57.0", + "eslint-plugin-react-hooks": "^4.6.2", + "eslint-plugin-react-refresh": "^0.4.7", + "fhevmjs": "^0.6.1", + "prettier": "^3.4.1", + "typescript": "^5.4.5", + "vite": "^5.4.11", + "vite-plugin-node-polyfills": "^0.22.0" + }, + "engines": { + "node": "^20.9.0" + } + }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@adraffy/ens-normalize": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", + "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==" + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.2.tgz", + "integrity": "sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz", + "integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.26.0", + "@babel/generator": "^7.26.0", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.0", + "@babel/parser": "^7.26.0", + "@babel/template": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.26.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.2.tgz", + "integrity": "sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.26.2", + "@babel/types": "^7.26.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz", + "integrity": "sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz", + "integrity": "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz", + "integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.25.9", + "@babel/types": "^7.26.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.2.tgz", + "integrity": "sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.26.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.9.tgz", + "integrity": "sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.25.9.tgz", + "integrity": "sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", + "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", + "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/template": "^7.25.9", + "@babel/types": "^7.25.9", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz", + "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.1.tgz", + "integrity": "sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@noble/curves": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", + "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", + "dependencies": { + "@noble/hashes": "1.3.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@rollup/plugin-inject": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@rollup/plugin-inject/-/plugin-inject-5.0.5.tgz", + "integrity": "sha512-2+DEJbNBoPROPkgTDNe8/1YXWcqxbN5DTjASVIOx8HS+pITXushyNiBV56RB08zuptzz8gT3YfkqriTBVycepg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.3" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.3.tgz", + "integrity": "sha512-Pnsb6f32CD2W3uCaLZIzDmeFyQ2b8UWMFI7xtwUezpcGBDVDW6y9XgAWIlARiGAo6eNF5FK5aQTr0LFyNyqq5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.27.4.tgz", + "integrity": "sha512-2Y3JT6f5MrQkICUyRVCw4oa0sutfAsgaSsb0Lmmy1Wi2y7X5vT9Euqw4gOsCyy0YfKURBg35nhUKZS4mDcfULw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.27.4.tgz", + "integrity": "sha512-wzKRQXISyi9UdCVRqEd0H4cMpzvHYt1f/C3CoIjES6cG++RHKhrBj2+29nPF0IB5kpy9MS71vs07fvrNGAl/iA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.27.4.tgz", + "integrity": "sha512-PlNiRQapift4LNS8DPUHuDX/IdXiLjf8mc5vdEmUR0fF/pyy2qWwzdLjB+iZquGr8LuN4LnUoSEvKRwjSVYz3Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.27.4.tgz", + "integrity": "sha512-o9bH2dbdgBDJaXWJCDTNDYa171ACUdzpxSZt+u/AAeQ20Nk5x+IhA+zsGmrQtpkLiumRJEYef68gcpn2ooXhSQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.27.4.tgz", + "integrity": "sha512-NBI2/i2hT9Q+HySSHTBh52da7isru4aAAo6qC3I7QFVsuhxi2gM8t/EI9EVcILiHLj1vfi+VGGPaLOUENn7pmw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.27.4.tgz", + "integrity": "sha512-wYcC5ycW2zvqtDYrE7deary2P2UFmSh85PUpAx+dwTCO9uw3sgzD6Gv9n5X4vLaQKsrfTSZZ7Z7uynQozPVvWA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.27.4.tgz", + "integrity": "sha512-9OwUnK/xKw6DyRlgx8UizeqRFOfi9mf5TYCw1uolDaJSbUmBxP85DE6T4ouCMoN6pXw8ZoTeZCSEfSaYo+/s1w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.27.4.tgz", + "integrity": "sha512-Vgdo4fpuphS9V24WOV+KwkCVJ72u7idTgQaBoLRD0UxBAWTF9GWurJO9YD9yh00BzbkhpeXtm6na+MvJU7Z73A==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.27.4.tgz", + "integrity": "sha512-pleyNgyd1kkBkw2kOqlBx+0atfIIkkExOTiifoODo6qKDSpnc6WzUY5RhHdmTdIJXBdSnh6JknnYTtmQyobrVg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.27.4.tgz", + "integrity": "sha512-caluiUXvUuVyCHr5DxL8ohaaFFzPGmgmMvwmqAITMpV/Q+tPoaHZ/PWa3t8B2WyoRcIIuu1hkaW5KkeTDNSnMA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.27.4.tgz", + "integrity": "sha512-FScrpHrO60hARyHh7s1zHE97u0KlT/RECzCKAdmI+LEoC1eDh/RDji9JgFqyO+wPDb86Oa/sXkily1+oi4FzJQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.27.4.tgz", + "integrity": "sha512-qyyprhyGb7+RBfMPeww9FlHwKkCXdKHeGgSqmIXw9VSUtvyFZ6WZRtnxgbuz76FK7LyoN8t/eINRbPUcvXB5fw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.27.4.tgz", + "integrity": "sha512-PFz+y2kb6tbh7m3A7nA9++eInGcDVZUACulf/KzDtovvdTizHpZaJty7Gp0lFwSQcrnebHOqxF1MaKZd7psVRg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.27.4.tgz", + "integrity": "sha512-Ni8mMtfo+o/G7DVtweXXV/Ol2TFf63KYjTtoZ5f078AUgJTmaIJnj4JFU7TK/9SVWTaSJGxPi5zMDgK4w+Ez7Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.27.4.tgz", + "integrity": "sha512-5AeeAF1PB9TUzD+3cROzFTnAJAcVUGLuR8ng0E0WXGkYhp6RD6L+6szYVX+64Rs0r72019KHZS1ka1q+zU/wUw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.27.4.tgz", + "integrity": "sha512-yOpVsA4K5qVwu2CaS3hHxluWIK5HQTjNV4tWjQXluMiiiu4pJj4BN98CvxohNCpcjMeTXk/ZMJBRbgRg8HBB6A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.27.4.tgz", + "integrity": "sha512-KtwEJOaHAVJlxV92rNYiG9JQwQAdhBlrjNRp7P9L8Cb4Rer3in+0A+IPhJC9y68WAi9H0sX4AiG2NTsVlmqJeQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.27.4.tgz", + "integrity": "sha512-3j4jx1TppORdTAoBJRd+/wJRGCPC0ETWkXOecJ6PPZLj6SptXkrXcNqdj0oclbKML6FkQltdz7bBA3rUSirZug==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@scure/base": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", + "integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.4.0.tgz", + "integrity": "sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==", + "dependencies": { + "@noble/curves": "~1.4.0", + "@noble/hashes": "~1.4.0", + "@scure/base": "~1.1.6" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32/node_modules/@noble/curves": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", + "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", + "dependencies": { + "@noble/hashes": "1.4.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32/node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip39": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.3.0.tgz", + "integrity": "sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==", + "dependencies": { + "@noble/hashes": "~1.4.0", + "@scure/base": "~1.1.6" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip39/node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/glob-to-regexp": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@types/glob-to-regexp/-/glob-to-regexp-0.4.4.tgz", + "integrity": "sha512-nDKoaKJYbnn1MZxUY0cA1bPmmgZbg0cTq7Rh13d0KWYNOiKbqoR+2d89SnRPszGh7ROzSwZ/GOjZ4jPbmmZ6Eg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "18.15.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.13.tgz", + "integrity": "sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==" + }, + "node_modules/@types/prop-types": { + "version": "15.7.5", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", + "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==", + "dev": true + }, + "node_modules/@types/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.1.tgz", + "integrity": "sha512-V0kuGBX3+prX+DQ/7r2qsv1NsdfnCLnTgnRJ1pYnxykBhGMz+qj+box5lq7XsO5mtZsBqpjwwTu/7wszPfMBcw==", + "dev": true, + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", + "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.13.1.tgz", + "integrity": "sha512-kZqi+WZQaZfPKnsflLJQCz6Ze9FFSMfXrrIOcyargekQxG37ES7DJNpJUE9Q/X5n3yTIP/WPutVNzgknQ7biLg==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "7.13.1", + "@typescript-eslint/type-utils": "7.13.1", + "@typescript-eslint/utils": "7.13.1", + "@typescript-eslint/visitor-keys": "7.13.1", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/type-utils": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.13.1.tgz", + "integrity": "sha512-aWDbLu1s9bmgPGXSzNCxELu+0+HQOapV/y+60gPXafR8e2g1Bifxzevaa+4L2ytCWm+CHqpELq4CSoN9ELiwCg==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "7.13.1", + "@typescript-eslint/utils": "7.13.1", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.13.1.tgz", + "integrity": "sha512-h5MzFBD5a/Gh/fvNdp9pTfqJAbuQC4sCN2WzuXme71lqFJsZtLbjxfSk4r3p02WIArOF9N94pdsLiGutpDbrXQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.13.1", + "@typescript-eslint/types": "7.13.1", + "@typescript-eslint/typescript-estree": "7.13.1" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.13.1.tgz", + "integrity": "sha512-1ELDPlnLvDQ5ybTSrMhRTFDfOQEOXNM+eP+3HT/Yq7ruWpciQw+Avi73pdEbA4SooCawEWo3dtYbF68gN7Ed1A==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "7.13.1", + "@typescript-eslint/types": "7.13.1", + "@typescript-eslint/typescript-estree": "7.13.1", + "@typescript-eslint/visitor-keys": "7.13.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.56.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.13.1.tgz", + "integrity": "sha512-adbXNVEs6GmbzaCpymHQ0MB6E4TqoiVbC0iqG3uijR8ZYfpAXMGttouQzF4Oat3P2GxDVIrg7bMI/P65LiQZdg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.13.1", + "@typescript-eslint/visitor-keys": "7.13.1" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.13.1.tgz", + "integrity": "sha512-7K7HMcSQIAND6RBL4kDl24sG/xKM13cA85dc7JnmQXw2cBDngg7c19B++JzvJHRG3zG36n9j1i451GBzRuHchw==", + "dev": true, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.13.1.tgz", + "integrity": "sha512-uxNr51CMV7npU1BxZzYjoVz9iyjckBduFBP0S5sLlh1tXYzHzgZ3BR9SVsNed+LmwKrmnqN3Kdl5t7eZ5TS1Yw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.13.1", + "@typescript-eslint/visitor-keys": "7.13.1", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.13.1.tgz", + "integrity": "sha512-k/Bfne7lrP7hcb7m9zSsgcBmo+8eicqqfNAJ7uUY+jkTFpKeH2FSkWpFRtimBxgkyvqfu9jTPRbYOvud6isdXA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "7.13.1", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || >=20.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "node_modules/@vitejs/plugin-react": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.4.tgz", + "integrity": "sha512-SCCPBJtYLdE8PX/7ZQAs1QAZ8Jqwih+0VBLum1EGqmCCQal+MIUqLCzj3ZUy8ufbC0cAM4LRlSTm7IQJwWT4ug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.26.0", + "@babel/plugin-transform-react-jsx-self": "^7.25.9", + "@babel/plugin-transform-react-jsx-source": "^7.25.9", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.14.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0" + } + }, + "node_modules/acorn": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz", + "integrity": "sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/aes-js": { + "version": "4.0.0-beta.5", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz", + "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==" + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/asn1.js/node_modules/bn.js": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "dev": true, + "license": "MIT" + }, + "node_modules/assert": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-2.1.0.tgz", + "integrity": "sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "is-nan": "^1.3.2", + "object-is": "^1.1.5", + "object.assign": "^4.1.4", + "util": "^0.12.5" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/bigint-buffer": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/bigint-buffer/-/bigint-buffer-1.1.5.tgz", + "integrity": "sha512-trfYco6AoZ+rKhKnxA0hgX0HAbVP/s808/EuDSe2JDzUnCp/xAsli35Orvk67UrTEcwuxZqYZDmfA2RXJgxVvA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "bindings": "^1.3.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bn.js": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", + "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", + "dev": true, + "license": "MIT" + }, + "node_modules/browser-resolve": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-2.0.0.tgz", + "integrity": "sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve": "^1.17.0" + } + }, + "node_modules/browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "node_modules/browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/browserify-rsa": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.1.tgz", + "integrity": "sha512-YBjSAiTqM04ZVei6sXighu679a3SqWORA3qZTEqZImnlkDIFtKc6pNutpjyZ8RJTjQtuYfeetkxM11GwoYXMIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^5.2.1", + "randombytes": "^2.1.0", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/browserify-sign": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.3.tgz", + "integrity": "sha512-JWCZW6SKhfhjJxO8Tyiiy+XYB7cqd2S5/+WeYHsKdNKFlCBhKbblba1A/HN/90YwtxKc8tCErjffZl++UNmGiw==", + "dev": true, + "license": "ISC", + "dependencies": { + "bn.js": "^5.2.1", + "browserify-rsa": "^4.1.0", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.5", + "hash-base": "~3.0", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.7", + "readable-stream": "^2.3.8", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/browserify-sign/node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/browserify-sign/node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/browserify-sign/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/browserify-sign/node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true, + "license": "MIT" + }, + "node_modules/browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pako": "~1.0.5" + } + }, + "node_modules/browserslist": { + "version": "4.24.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", + "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "caniuse-lite": "^1.0.30001669", + "electron-to-chromium": "^1.5.41", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.1" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001684", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001684.tgz", + "integrity": "sha512-G1LRwLIQjBQoyq0ZJGqGIJUXzJ8irpbjHLpVRXDvBEScFJ9b17sgK6vlx0GAJFE21okD7zXl08rRRUfq6HdoEQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/cipher-base": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.6.tgz", + "integrity": "sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/commander": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.0.0.tgz", + "integrity": "sha512-9HMlXtt/BNoYr8ooyjjNRdIilOTkVJXB+GhxMTtOKwk0R4j4lS4NpjuqmRxroBfnfTSHQIHQB7wryHhXarNjmQ==", + "dev": true, + "engines": { + "node": ">=16" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", + "dev": true + }, + "node_modules/constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + } + }, + "node_modules/create-ecdh/node_modules/bn.js": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "dev": true, + "license": "MIT" + }, + "node_modules/create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-browserify": { + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.1.tgz", + "integrity": "sha512-r4ESw/IlusD17lgQi1O20Fa3qNnsckR126TdUuBgAu7GBYSIPvdNyONd3Zrxh0xCwA4+6w/TDArBPsMvhur+KQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "browserify-cipher": "^1.0.1", + "browserify-sign": "^4.2.3", + "create-ecdh": "^4.0.4", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "diffie-hellman": "^5.0.3", + "hash-base": "~3.0.4", + "inherits": "^2.0.4", + "pbkdf2": "^3.1.2", + "public-encrypt": "^4.0.3", + "randombytes": "^2.1.0", + "randomfill": "^1.0.4" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/csstype": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", + "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==", + "dev": true + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/des.js": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.1.0.tgz", + "integrity": "sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "node_modules/diffie-hellman/node_modules/bn.js": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "dev": true, + "license": "MIT" + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/domain-browser": { + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-4.22.0.tgz", + "integrity": "sha512-IGBwjF7tNk3cwypFNH/7bfzBcgSCbaMOD3GsaY1AU/JRrnHnYgEM0+9kQt52iZxjNsjBtJYtao146V+f8jFZNw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://bevry.me/fund" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.65", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.65.tgz", + "integrity": "sha512-PWVzBjghx7/wop6n22vS2MLU8tKGd4Q91aCEGhG/TYmW6PP5OcSXcdnxTe1NNt0T66N8D6jxh4kC8UsdzOGaIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/elliptic": { + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz", + "integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "dev": true, + "license": "MIT" + }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/eslint": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", + "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/eslint-plugin-react-refresh": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.7.tgz", + "integrity": "sha512-yrj+KInFmwuQS2UQcg1SF83ha1tuHC1jMQbRNyuWtlEzzKRDgAl7L4Yp4NlDUZTZNlWvHEzOtJhMi40R7JxcSw==", + "dev": true, + "peerDependencies": { + "eslint": ">=7" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ethereum-cryptography": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", + "integrity": "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==", + "dependencies": { + "@noble/curves": "1.4.2", + "@noble/hashes": "1.4.0", + "@scure/bip32": "1.4.0", + "@scure/bip39": "1.3.0" + } + }, + "node_modules/ethereum-cryptography/node_modules/@noble/curves": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", + "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", + "dependencies": { + "@noble/hashes": "1.4.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ethereum-cryptography/node_modules/@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/ethers": { + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.13.1.tgz", + "integrity": "sha512-hdJ2HOxg/xx97Lm9HdCWk949BfYqYWpyw4//78SiwOLgASyfrNszfMUNB2joKjvGUdwhHfaiMMFFwacVVoLR9A==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/ethers-io/" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "dependencies": { + "@adraffy/ens-normalize": "1.10.1", + "@noble/curves": "1.2.0", + "@noble/hashes": "1.3.2", + "@types/node": "18.15.13", + "aes-js": "4.0.0-beta.5", + "tslib": "2.4.0", + "ws": "8.17.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/ethers/node_modules/tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fetch-mock": { + "version": "11.1.5", + "resolved": "https://registry.npmjs.org/fetch-mock/-/fetch-mock-11.1.5.tgz", + "integrity": "sha512-KHmZDnZ1ry0pCTrX4YG5DtThHi0MH+GNI9caESnzX/nMJBrvppUHMvLx47M0WY9oAtKOMiPfZDRpxhlHg89BOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/glob-to-regexp": "^0.4.4", + "dequal": "^2.0.3", + "glob-to-regexp": "^0.4.1", + "is-subset": "^0.1.1", + "regexparam": "^3.0.0" + }, + "engines": { + "node": ">=8.0.0" + }, + "peerDependenciesMeta": { + "node-fetch": { + "optional": true + } + } + }, + "node_modules/fhevmjs": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/fhevmjs/-/fhevmjs-0.6.1.tgz", + "integrity": "sha512-y8G92We5oHHIunA7TykvUR5Sv1jYEQmBfEHJZb6q3GZRPoaHPbmN5QB+R+6NmVk/dch9osbjUnMlGZe7tV4bQA==", + "dev": true, + "dependencies": { + "bigint-buffer": "^1.1.5", + "commander": "^11.0.0", + "fetch-mock": "^11.1.3", + "keccak": "^3.0.4", + "node-tfhe": "^0.9.1", + "node-tkms": "^0.9.0", + "tfhe": "^0.9.1", + "tkms": "^0.9.0", + "wasm-feature-detect": "^1.8.0" + }, + "bin": { + "fhevm": "bin/fhevm.js" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hash-base": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.5.tgz", + "integrity": "sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/idb": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/idb/-/idb-8.0.0.tgz", + "integrity": "sha512-l//qvlAKGmQO31Qn7xdzagVPPaHTxXx199MhrAFuVBTPqydcPYBWjkrbv4Y0ktB+GmWOiwHl237UUOrLmQxLvw==", + "license": "ISC" + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-nan": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", + "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-subset": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz", + "integrity": "sha512-6Ybun0IkarhmEqxXCNw/C0bna6Zb/TkfUX9UbwJtK6ObwAVCxmAP308WWTHviM/zAqXk05cdhYsUsZeGQh99iw==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "dependencies": { + "which-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/isomorphic-timers-promises": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/isomorphic-timers-promises/-/isomorphic-timers-promises-1.0.1.tgz", + "integrity": "sha512-u4sej9B1LPSxTGKB/HiuzvEQnXH0ECYkSVQU39koSwmFAxhlEAFl9RdTvLv4TOTQUgBS5O3O5fwUxk6byBZ+IQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/keccak": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.4.tgz", + "integrity": "sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/magic-string": { + "version": "0.30.14", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.14.tgz", + "integrity": "sha512-5c99P1WKTed11ZC0HMJOj6CDIue6F8ySu+bJL+85q1zBEIY8IklrJ1eiKC2NDRh3Ct3FcvmJPyQHb9erXMTJNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "license": "MIT", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "bin": { + "miller-rabin": "bin/miller-rabin" + } + }, + "node_modules/miller-rabin/node_modules/bn.js": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "dev": true, + "license": "MIT" + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true, + "license": "ISC" + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", + "dev": true, + "license": "MIT" + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/node-addon-api": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", + "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-gyp-build": { + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", + "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", + "dev": true, + "license": "MIT", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/node-releases": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-stdlib-browser": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/node-stdlib-browser/-/node-stdlib-browser-1.3.0.tgz", + "integrity": "sha512-g/koYzOr9Fb1Jc+tHUHlFd5gODjGn48tHexUK8q6iqOVriEgSnd3/1T7myBYc+0KBVze/7F7n65ec9rW6OD7xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "assert": "^2.0.0", + "browser-resolve": "^2.0.0", + "browserify-zlib": "^0.2.0", + "buffer": "^5.7.1", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "create-require": "^1.1.1", + "crypto-browserify": "^3.11.0", + "domain-browser": "4.22.0", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "isomorphic-timers-promises": "^1.0.1", + "os-browserify": "^0.3.0", + "path-browserify": "^1.0.1", + "pkg-dir": "^5.0.0", + "process": "^0.11.10", + "punycode": "^1.4.1", + "querystring-es3": "^0.2.1", + "readable-stream": "^3.6.0", + "stream-browserify": "^3.0.0", + "stream-http": "^3.2.0", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.1", + "url": "^0.11.4", + "util": "^0.12.4", + "vm-browserify": "^1.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-stdlib-browser/node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/node-stdlib-browser/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-tfhe": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/node-tfhe/-/node-tfhe-0.9.1.tgz", + "integrity": "sha512-M2CbUVX4DQneaaK/4fygy9lW0zjOOzM8yGWAgbKGRt/Gd07zaloFEGGHW7dbmUaHo022q1uo7nzxyYhe4UgqCw==", + "dev": true, + "license": "BSD-3-Clause-Clear" + }, + "node_modules/node-tkms": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/node-tkms/-/node-tkms-0.9.0.tgz", + "integrity": "sha512-ulhV23okeMW3WYnxzhvf9u87tcXqe64JqUFlvdgu64uKteG8re+zwOjzkOdxvF0xSWQbMtEU96dvcrvQM10PEg==", + "dev": true + }, + "node_modules/object-inspect": { + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", + "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==", + "dev": true, + "license": "MIT" + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true, + "license": "(MIT AND Zlib)" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-asn1": { + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.7.tgz", + "integrity": "sha512-CTM5kuWR3sx9IFamcl5ErfPl6ea/N8IYwiJ+vpeB2g+1iknv7zBl5uPwbMbRVznRVbrNY6lGuDoE5b30grmbqg==", + "dev": true, + "license": "ISC", + "dependencies": { + "asn1.js": "^4.10.1", + "browserify-aes": "^1.2.0", + "evp_bytestokey": "^1.0.3", + "hash-base": "~3.0", + "pbkdf2": "^3.1.2", + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/pbkdf2": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pkg-dir": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", + "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^5.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.4.49", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", + "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.1.tgz", + "integrity": "sha512-G+YdqtITVZmOJje6QkXQWzl3fSfMxFwm1tjTyo9exhkmWSqC4Yhd1+lug++IlR2mvRVAxEDDWYkQdeSztajqgg==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true, + "license": "MIT" + }, + "node_modules/public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/public-encrypt/node_modules/bn.js": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "dev": true, + "license": "MIT" + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.1.tgz", + "integrity": "sha512-EJPeIn0CYrGu+hli1xilKAPXODtJ12T0sP63Ijx2/khC2JtuaN3JyNIpvmnkmaEtha9ocbG4A4cMcr+TvqvwQg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==", + "dev": true, + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-refresh": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", + "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/regexparam": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/regexparam/-/regexparam-3.0.0.tgz", + "integrity": "sha512-RSYAtP31mvYLkAHrOlh25pCNQ5hWnT106VukGaaFfuJrZFkGRX5GhUAdPqpSDXxOhA2c4akmRuplv1mRqnBn6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/rollup": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.27.4.tgz", + "integrity": "sha512-RLKxqHEMjh/RGLsDxAEsaLO3mWgyoU6x9w6n1ikAzet4B3gI2/3yP6PWY2p9QzRTh6MfEIXB3MwsOY0Iv3vNrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.6" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.27.4", + "@rollup/rollup-android-arm64": "4.27.4", + "@rollup/rollup-darwin-arm64": "4.27.4", + "@rollup/rollup-darwin-x64": "4.27.4", + "@rollup/rollup-freebsd-arm64": "4.27.4", + "@rollup/rollup-freebsd-x64": "4.27.4", + "@rollup/rollup-linux-arm-gnueabihf": "4.27.4", + "@rollup/rollup-linux-arm-musleabihf": "4.27.4", + "@rollup/rollup-linux-arm64-gnu": "4.27.4", + "@rollup/rollup-linux-arm64-musl": "4.27.4", + "@rollup/rollup-linux-powerpc64le-gnu": "4.27.4", + "@rollup/rollup-linux-riscv64-gnu": "4.27.4", + "@rollup/rollup-linux-s390x-gnu": "4.27.4", + "@rollup/rollup-linux-x64-gnu": "4.27.4", + "@rollup/rollup-linux-x64-musl": "4.27.4", + "@rollup/rollup-win32-arm64-msvc": "4.27.4", + "@rollup/rollup-win32-ia32-msvc": "4.27.4", + "@rollup/rollup-win32-x64-msvc": "4.27.4", + "fsevents": "~2.3.2" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true, + "license": "MIT" + }, + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "license": "(MIT AND BSD-3-Clause)", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stream-browserify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", + "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "~2.0.4", + "readable-stream": "^3.5.0" + } + }, + "node_modules/stream-http": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.2.0.tgz", + "integrity": "sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==", + "dev": true, + "license": "MIT", + "dependencies": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "xtend": "^4.0.2" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "node_modules/tfhe": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/tfhe/-/tfhe-0.9.1.tgz", + "integrity": "sha512-kmtl7KfCCZJaFhm9lUYsTtat+yT0qzOiO6bOidM2Pt7/7jptkbS2/myeGHxb9qi2/aJ30g2joo1euKZPa207tg==", + "dev": true, + "license": "BSD-3-Clause-Clear" + }, + "node_modules/timers-browserify": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", + "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "setimmediate": "^1.0.4" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/tkms": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/tkms/-/tkms-0.9.0.tgz", + "integrity": "sha512-dSzorTHvIXTYZtn6ACV/iz0GhO/kMRjqGbo3o7JJ3GNbFhsPzbIEtAQ/x+h9nJdwn//VRdsStnOAE0fxUVIGrQ==", + "dev": true + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "dev": true, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, + "node_modules/tty-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", + "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==", + "dev": true, + "license": "MIT" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/url": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.4.tgz", + "integrity": "sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^1.4.1", + "qs": "^6.12.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/url/node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "dev": true + }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/vite": { + "version": "5.4.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz", + "integrity": "sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vite-plugin-node-polyfills": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/vite-plugin-node-polyfills/-/vite-plugin-node-polyfills-0.22.0.tgz", + "integrity": "sha512-F+G3LjiGbG8QpbH9bZ//GSBr9i1InSTkaulfUHFa9jkLqVGORFBoqc2A/Yu5Mmh1kNAbiAeKeK+6aaQUf3x0JA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/plugin-inject": "^5.0.5", + "node-stdlib-browser": "^1.2.0" + }, + "funding": { + "url": "https://github.com/sponsors/davidmyersdev" + }, + "peerDependencies": { + "vite": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0" + } + }, + "node_modules/vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/wasm-feature-detect": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/wasm-feature-detect/-/wasm-feature-detect-1.8.0.tgz", + "integrity": "sha512-zksaLKM2fVlnB5jQQDqKXXwYHLQUVH9es+5TOOHwGOVJOCeRBCiPjwSg+3tN2AdTCzjgli4jijCH290kXb/zWQ==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/web3-errors": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/web3-errors/-/web3-errors-1.3.1.tgz", + "integrity": "sha512-w3NMJujH+ZSW4ltIZZKtdbkbyQEvBzyp3JRn59Ckli0Nz4VMsVq8aF1bLWM7A2kuQ+yVEm3ySeNU+7mSRwx7RQ==", + "dependencies": { + "web3-types": "^1.10.0" + }, + "engines": { + "node": ">=14", + "npm": ">=6.12.0" + } + }, + "node_modules/web3-types": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/web3-types/-/web3-types-1.10.0.tgz", + "integrity": "sha512-0IXoaAFtFc8Yin7cCdQfB9ZmjafrbP6BO0f0KT/khMhXKUpoJ6yShrVhiNpyRBo8QQjuOagsWzwSK2H49I7sbw==", + "engines": { + "node": ">=14", + "npm": ">=6.12.0" + } + }, + "node_modules/web3-validator": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/web3-validator/-/web3-validator-2.0.6.tgz", + "integrity": "sha512-qn9id0/l1bWmvH4XfnG/JtGKKwut2Vokl6YXP5Kfg424npysmtRLe9DgiNBM9Op7QL/aSiaA0TVXibuIuWcizg==", + "dependencies": { + "ethereum-cryptography": "^2.0.0", + "util": "^0.12.5", + "web3-errors": "^1.2.0", + "web3-types": "^1.6.0", + "zod": "^3.21.4" + }, + "engines": { + "node": ">=14", + "npm": ">=6.12.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "3.24.1", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.1.tgz", + "integrity": "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + } + }, + "dependencies": { + "@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true + }, + "@adraffy/ens-normalize": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", + "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==" + }, + "@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "requires": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "@babel/code-frame": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + } + }, + "@babel/compat-data": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.2.tgz", + "integrity": "sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg==", + "dev": true + }, + "@babel/core": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz", + "integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==", + "dev": true, + "requires": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.26.0", + "@babel/generator": "^7.26.0", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.0", + "@babel/parser": "^7.26.0", + "@babel/template": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.26.0", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.2.tgz", + "integrity": "sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==", + "dev": true, + "requires": { + "@babel/parser": "^7.26.2", + "@babel/types": "^7.26.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz", + "integrity": "sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true + } + } + }, + "@babel/helper-module-imports": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "dev": true, + "requires": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + } + }, + "@babel/helper-module-transforms": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz", + "integrity": "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==", + "dev": true + }, + "@babel/helper-string-parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "dev": true + }, + "@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", + "dev": true + }, + "@babel/helpers": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz", + "integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==", + "dev": true, + "requires": { + "@babel/template": "^7.25.9", + "@babel/types": "^7.26.0" + } + }, + "@babel/parser": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.2.tgz", + "integrity": "sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==", + "dev": true, + "requires": { + "@babel/types": "^7.26.0" + } + }, + "@babel/plugin-transform-react-jsx-self": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.9.tgz", + "integrity": "sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/plugin-transform-react-jsx-source": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.25.9.tgz", + "integrity": "sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.25.9" + } + }, + "@babel/template": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", + "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/types": "^7.25.9" + } + }, + "@babel/traverse": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", + "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/template": "^7.25.9", + "@babel/types": "^7.25.9", + "debug": "^4.3.1", + "globals": "^11.1.0" + } + }, + "@babel/types": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz", + "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==", + "dev": true, + "requires": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" + } + }, + "@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "dev": true, + "optional": true + }, + "@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "dev": true, + "optional": true + }, + "@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "dev": true, + "optional": true + }, + "@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "dev": true, + "optional": true + }, + "@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "dev": true, + "optional": true + }, + "@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "dev": true, + "optional": true + }, + "@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "dev": true, + "optional": true + }, + "@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "dev": true, + "optional": true + }, + "@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "dev": true, + "optional": true + }, + "@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "dev": true, + "optional": true + }, + "@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "dev": true, + "optional": true + }, + "@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "dev": true, + "optional": true + }, + "@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "dev": true, + "optional": true + }, + "@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "dev": true, + "optional": true + }, + "@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "dev": true, + "optional": true + }, + "@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "dev": true, + "optional": true + }, + "@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^3.3.0" + } + }, + "@eslint-community/regexpp": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.1.tgz", + "integrity": "sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA==", + "dev": true + }, + "@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + } + } + }, + "@eslint/js": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "dev": true + }, + "@humanwhocodes/config-array": { + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + } + }, + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true + }, + "@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "dev": true + }, + "@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, + "requires": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true + }, + "@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true + }, + "@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true + }, + "@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "requires": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "@noble/curves": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", + "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", + "requires": { + "@noble/hashes": "1.3.2" + } + }, + "@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==" + }, + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@rollup/plugin-inject": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@rollup/plugin-inject/-/plugin-inject-5.0.5.tgz", + "integrity": "sha512-2+DEJbNBoPROPkgTDNe8/1YXWcqxbN5DTjASVIOx8HS+pITXushyNiBV56RB08zuptzz8gT3YfkqriTBVycepg==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^5.0.1", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.3" + } + }, + "@rollup/pluginutils": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.3.tgz", + "integrity": "sha512-Pnsb6f32CD2W3uCaLZIzDmeFyQ2b8UWMFI7xtwUezpcGBDVDW6y9XgAWIlARiGAo6eNF5FK5aQTr0LFyNyqq5A==", + "dev": true, + "requires": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^4.0.2" + }, + "dependencies": { + "picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "dev": true + } + } + }, + "@rollup/rollup-android-arm-eabi": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.27.4.tgz", + "integrity": "sha512-2Y3JT6f5MrQkICUyRVCw4oa0sutfAsgaSsb0Lmmy1Wi2y7X5vT9Euqw4gOsCyy0YfKURBg35nhUKZS4mDcfULw==", + "dev": true, + "optional": true + }, + "@rollup/rollup-android-arm64": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.27.4.tgz", + "integrity": "sha512-wzKRQXISyi9UdCVRqEd0H4cMpzvHYt1f/C3CoIjES6cG++RHKhrBj2+29nPF0IB5kpy9MS71vs07fvrNGAl/iA==", + "dev": true, + "optional": true + }, + "@rollup/rollup-darwin-arm64": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.27.4.tgz", + "integrity": "sha512-PlNiRQapift4LNS8DPUHuDX/IdXiLjf8mc5vdEmUR0fF/pyy2qWwzdLjB+iZquGr8LuN4LnUoSEvKRwjSVYz3Q==", + "dev": true, + "optional": true + }, + "@rollup/rollup-darwin-x64": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.27.4.tgz", + "integrity": "sha512-o9bH2dbdgBDJaXWJCDTNDYa171ACUdzpxSZt+u/AAeQ20Nk5x+IhA+zsGmrQtpkLiumRJEYef68gcpn2ooXhSQ==", + "dev": true, + "optional": true + }, + "@rollup/rollup-freebsd-arm64": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.27.4.tgz", + "integrity": "sha512-NBI2/i2hT9Q+HySSHTBh52da7isru4aAAo6qC3I7QFVsuhxi2gM8t/EI9EVcILiHLj1vfi+VGGPaLOUENn7pmw==", + "dev": true, + "optional": true + }, + "@rollup/rollup-freebsd-x64": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.27.4.tgz", + "integrity": "sha512-wYcC5ycW2zvqtDYrE7deary2P2UFmSh85PUpAx+dwTCO9uw3sgzD6Gv9n5X4vLaQKsrfTSZZ7Z7uynQozPVvWA==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.27.4.tgz", + "integrity": "sha512-9OwUnK/xKw6DyRlgx8UizeqRFOfi9mf5TYCw1uolDaJSbUmBxP85DE6T4ouCMoN6pXw8ZoTeZCSEfSaYo+/s1w==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-arm-musleabihf": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.27.4.tgz", + "integrity": "sha512-Vgdo4fpuphS9V24WOV+KwkCVJ72u7idTgQaBoLRD0UxBAWTF9GWurJO9YD9yh00BzbkhpeXtm6na+MvJU7Z73A==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-arm64-gnu": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.27.4.tgz", + "integrity": "sha512-pleyNgyd1kkBkw2kOqlBx+0atfIIkkExOTiifoODo6qKDSpnc6WzUY5RhHdmTdIJXBdSnh6JknnYTtmQyobrVg==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-arm64-musl": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.27.4.tgz", + "integrity": "sha512-caluiUXvUuVyCHr5DxL8ohaaFFzPGmgmMvwmqAITMpV/Q+tPoaHZ/PWa3t8B2WyoRcIIuu1hkaW5KkeTDNSnMA==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.27.4.tgz", + "integrity": "sha512-FScrpHrO60hARyHh7s1zHE97u0KlT/RECzCKAdmI+LEoC1eDh/RDji9JgFqyO+wPDb86Oa/sXkily1+oi4FzJQ==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-riscv64-gnu": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.27.4.tgz", + "integrity": "sha512-qyyprhyGb7+RBfMPeww9FlHwKkCXdKHeGgSqmIXw9VSUtvyFZ6WZRtnxgbuz76FK7LyoN8t/eINRbPUcvXB5fw==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-s390x-gnu": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.27.4.tgz", + "integrity": "sha512-PFz+y2kb6tbh7m3A7nA9++eInGcDVZUACulf/KzDtovvdTizHpZaJty7Gp0lFwSQcrnebHOqxF1MaKZd7psVRg==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-x64-gnu": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.27.4.tgz", + "integrity": "sha512-Ni8mMtfo+o/G7DVtweXXV/Ol2TFf63KYjTtoZ5f078AUgJTmaIJnj4JFU7TK/9SVWTaSJGxPi5zMDgK4w+Ez7Q==", + "dev": true, + "optional": true + }, + "@rollup/rollup-linux-x64-musl": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.27.4.tgz", + "integrity": "sha512-5AeeAF1PB9TUzD+3cROzFTnAJAcVUGLuR8ng0E0WXGkYhp6RD6L+6szYVX+64Rs0r72019KHZS1ka1q+zU/wUw==", + "dev": true, + "optional": true + }, + "@rollup/rollup-win32-arm64-msvc": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.27.4.tgz", + "integrity": "sha512-yOpVsA4K5qVwu2CaS3hHxluWIK5HQTjNV4tWjQXluMiiiu4pJj4BN98CvxohNCpcjMeTXk/ZMJBRbgRg8HBB6A==", + "dev": true, + "optional": true + }, + "@rollup/rollup-win32-ia32-msvc": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.27.4.tgz", + "integrity": "sha512-KtwEJOaHAVJlxV92rNYiG9JQwQAdhBlrjNRp7P9L8Cb4Rer3in+0A+IPhJC9y68WAi9H0sX4AiG2NTsVlmqJeQ==", + "dev": true, + "optional": true + }, + "@rollup/rollup-win32-x64-msvc": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.27.4.tgz", + "integrity": "sha512-3j4jx1TppORdTAoBJRd+/wJRGCPC0ETWkXOecJ6PPZLj6SptXkrXcNqdj0oclbKML6FkQltdz7bBA3rUSirZug==", + "dev": true, + "optional": true + }, + "@scure/base": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", + "integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==" + }, + "@scure/bip32": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.4.0.tgz", + "integrity": "sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==", + "requires": { + "@noble/curves": "~1.4.0", + "@noble/hashes": "~1.4.0", + "@scure/base": "~1.1.6" + }, + "dependencies": { + "@noble/curves": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", + "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", + "requires": { + "@noble/hashes": "1.4.0" + } + }, + "@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==" + } + } + }, + "@scure/bip39": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.3.0.tgz", + "integrity": "sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==", + "requires": { + "@noble/hashes": "~1.4.0", + "@scure/base": "~1.1.6" + }, + "dependencies": { + "@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==" + } + } + }, + "@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "requires": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "requires": { + "@babel/types": "^7.0.0" + } + }, + "@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "requires": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "@types/babel__traverse": { + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "dev": true, + "requires": { + "@babel/types": "^7.20.7" + } + }, + "@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true + }, + "@types/glob-to-regexp": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@types/glob-to-regexp/-/glob-to-regexp-0.4.4.tgz", + "integrity": "sha512-nDKoaKJYbnn1MZxUY0cA1bPmmgZbg0cTq7Rh13d0KWYNOiKbqoR+2d89SnRPszGh7ROzSwZ/GOjZ4jPbmmZ6Eg==", + "dev": true + }, + "@types/node": { + "version": "18.15.13", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.13.tgz", + "integrity": "sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==" + }, + "@types/prop-types": { + "version": "15.7.5", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", + "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==", + "dev": true + }, + "@types/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.1.tgz", + "integrity": "sha512-V0kuGBX3+prX+DQ/7r2qsv1NsdfnCLnTgnRJ1pYnxykBhGMz+qj+box5lq7XsO5mtZsBqpjwwTu/7wszPfMBcw==", + "dev": true, + "requires": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "@types/react-dom": { + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", + "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", + "dev": true, + "requires": { + "@types/react": "*" + } + }, + "@typescript-eslint/eslint-plugin": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.13.1.tgz", + "integrity": "sha512-kZqi+WZQaZfPKnsflLJQCz6Ze9FFSMfXrrIOcyargekQxG37ES7DJNpJUE9Q/X5n3yTIP/WPutVNzgknQ7biLg==", + "dev": true, + "requires": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "7.13.1", + "@typescript-eslint/type-utils": "7.13.1", + "@typescript-eslint/utils": "7.13.1", + "@typescript-eslint/visitor-keys": "7.13.1", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + }, + "dependencies": { + "@typescript-eslint/type-utils": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.13.1.tgz", + "integrity": "sha512-aWDbLu1s9bmgPGXSzNCxELu+0+HQOapV/y+60gPXafR8e2g1Bifxzevaa+4L2ytCWm+CHqpELq4CSoN9ELiwCg==", + "dev": true, + "requires": { + "@typescript-eslint/typescript-estree": "7.13.1", + "@typescript-eslint/utils": "7.13.1", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + } + }, + "@typescript-eslint/utils": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.13.1.tgz", + "integrity": "sha512-h5MzFBD5a/Gh/fvNdp9pTfqJAbuQC4sCN2WzuXme71lqFJsZtLbjxfSk4r3p02WIArOF9N94pdsLiGutpDbrXQ==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "7.13.1", + "@typescript-eslint/types": "7.13.1", + "@typescript-eslint/typescript-estree": "7.13.1" + } + } + } + }, + "@typescript-eslint/parser": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.13.1.tgz", + "integrity": "sha512-1ELDPlnLvDQ5ybTSrMhRTFDfOQEOXNM+eP+3HT/Yq7ruWpciQw+Avi73pdEbA4SooCawEWo3dtYbF68gN7Ed1A==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "7.13.1", + "@typescript-eslint/types": "7.13.1", + "@typescript-eslint/typescript-estree": "7.13.1", + "@typescript-eslint/visitor-keys": "7.13.1", + "debug": "^4.3.4" + } + }, + "@typescript-eslint/scope-manager": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.13.1.tgz", + "integrity": "sha512-adbXNVEs6GmbzaCpymHQ0MB6E4TqoiVbC0iqG3uijR8ZYfpAXMGttouQzF4Oat3P2GxDVIrg7bMI/P65LiQZdg==", + "dev": true, + "requires": { + "@typescript-eslint/types": "7.13.1", + "@typescript-eslint/visitor-keys": "7.13.1" + } + }, + "@typescript-eslint/types": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.13.1.tgz", + "integrity": "sha512-7K7HMcSQIAND6RBL4kDl24sG/xKM13cA85dc7JnmQXw2cBDngg7c19B++JzvJHRG3zG36n9j1i451GBzRuHchw==", + "dev": true + }, + "@typescript-eslint/typescript-estree": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.13.1.tgz", + "integrity": "sha512-uxNr51CMV7npU1BxZzYjoVz9iyjckBduFBP0S5sLlh1tXYzHzgZ3BR9SVsNed+LmwKrmnqN3Kdl5t7eZ5TS1Yw==", + "dev": true, + "requires": { + "@typescript-eslint/types": "7.13.1", + "@typescript-eslint/visitor-keys": "7.13.1", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", + "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "@typescript-eslint/visitor-keys": { + "version": "7.13.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.13.1.tgz", + "integrity": "sha512-k/Bfne7lrP7hcb7m9zSsgcBmo+8eicqqfNAJ7uUY+jkTFpKeH2FSkWpFRtimBxgkyvqfu9jTPRbYOvud6isdXA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "7.13.1", + "eslint-visitor-keys": "^3.4.3" + } + }, + "@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, + "@vitejs/plugin-react": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.4.tgz", + "integrity": "sha512-SCCPBJtYLdE8PX/7ZQAs1QAZ8Jqwih+0VBLum1EGqmCCQal+MIUqLCzj3ZUy8ufbC0cAM4LRlSTm7IQJwWT4ug==", + "dev": true, + "requires": { + "@babel/core": "^7.26.0", + "@babel/plugin-transform-react-jsx-self": "^7.25.9", + "@babel/plugin-transform-react-jsx-source": "^7.25.9", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.14.2" + } + }, + "acorn": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.0.tgz", + "integrity": "sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==", + "dev": true + }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "requires": {} + }, + "aes-js": { + "version": "4.0.0-beta.5", + "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz", + "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==" + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "asn1.js": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "dev": true + } + } + }, + "assert": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-2.1.0.tgz", + "integrity": "sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "is-nan": "^1.3.2", + "object-is": "^1.1.5", + "object.assign": "^4.1.4", + "util": "^0.12.5" + } + }, + "available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "requires": { + "possible-typed-array-names": "^1.0.0" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true + }, + "bigint-buffer": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/bigint-buffer/-/bigint-buffer-1.1.5.tgz", + "integrity": "sha512-trfYco6AoZ+rKhKnxA0hgX0HAbVP/s808/EuDSe2JDzUnCp/xAsli35Orvk67UrTEcwuxZqYZDmfA2RXJgxVvA==", + "dev": true, + "requires": { + "bindings": "^1.3.0" + } + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bn.js": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz", + "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==", + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "requires": { + "fill-range": "^7.1.1" + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", + "dev": true + }, + "browser-resolve": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-2.0.0.tgz", + "integrity": "sha512-7sWsQlYL2rGLy2IWm8WL8DCTJvYLc/qlOnsakDac87SOoCd16WLsaAMdCiAqsTNHIe+SXfaqyxyo6THoWqs8WQ==", + "dev": true, + "requires": { + "resolve": "^1.17.0" + } + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "browserify-rsa": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.1.tgz", + "integrity": "sha512-YBjSAiTqM04ZVei6sXighu679a3SqWORA3qZTEqZImnlkDIFtKc6pNutpjyZ8RJTjQtuYfeetkxM11GwoYXMIQ==", + "dev": true, + "requires": { + "bn.js": "^5.2.1", + "randombytes": "^2.1.0", + "safe-buffer": "^5.2.1" + } + }, + "browserify-sign": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.3.tgz", + "integrity": "sha512-JWCZW6SKhfhjJxO8Tyiiy+XYB7cqd2S5/+WeYHsKdNKFlCBhKbblba1A/HN/90YwtxKc8tCErjffZl++UNmGiw==", + "dev": true, + "requires": { + "bn.js": "^5.2.1", + "browserify-rsa": "^4.1.0", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.5", + "hash-base": "~3.0", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.7", + "readable-stream": "^2.3.8", + "safe-buffer": "^5.2.1" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } + } + } + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "requires": { + "pako": "~1.0.5" + } + }, + "browserslist": { + "version": "4.24.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", + "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001669", + "electron-to-chromium": "^1.5.41", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.1" + } + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==", + "dev": true + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==", + "dev": true + }, + "call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "requires": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "caniuse-lite": { + "version": "1.0.30001684", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001684.tgz", + "integrity": "sha512-G1LRwLIQjBQoyq0ZJGqGIJUXzJ8irpbjHLpVRXDvBEScFJ9b17sgK6vlx0GAJFE21okD7zXl08rRRUfq6HdoEQ==", + "dev": true + }, + "cipher-base": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.6.tgz", + "integrity": "sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==", + "dev": true, + "requires": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1" + } + }, + "commander": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.0.0.tgz", + "integrity": "sha512-9HMlXtt/BNoYr8ooyjjNRdIilOTkVJXB+GhxMTtOKwk0R4j4lS4NpjuqmRxroBfnfTSHQIHQB7wryHhXarNjmQ==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", + "dev": true + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==", + "dev": true + }, + "convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + }, + "dependencies": { + "bn.js": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "dev": true + } + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "crypto-browserify": { + "version": "3.12.1", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.1.tgz", + "integrity": "sha512-r4ESw/IlusD17lgQi1O20Fa3qNnsckR126TdUuBgAu7GBYSIPvdNyONd3Zrxh0xCwA4+6w/TDArBPsMvhur+KQ==", + "dev": true, + "requires": { + "browserify-cipher": "^1.0.1", + "browserify-sign": "^4.2.3", + "create-ecdh": "^4.0.4", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "diffie-hellman": "^5.0.3", + "hash-base": "~3.0.4", + "inherits": "^2.0.4", + "pbkdf2": "^3.1.2", + "public-encrypt": "^4.0.3", + "randombytes": "^2.1.0", + "randomfill": "^1.0.4" + } + }, + "csstype": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", + "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==", + "dev": true + }, + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "requires": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + } + }, + "define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "requires": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + } + }, + "dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true + }, + "des.js": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.1.0.tgz", + "integrity": "sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "dev": true + } + } + }, + "dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "requires": { + "path-type": "^4.0.0" + } + }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "domain-browser": { + "version": "4.22.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-4.22.0.tgz", + "integrity": "sha512-IGBwjF7tNk3cwypFNH/7bfzBcgSCbaMOD3GsaY1AU/JRrnHnYgEM0+9kQt52iZxjNsjBtJYtao146V+f8jFZNw==", + "dev": true + }, + "electron-to-chromium": { + "version": "1.5.65", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.65.tgz", + "integrity": "sha512-PWVzBjghx7/wop6n22vS2MLU8tKGd4Q91aCEGhG/TYmW6PP5OcSXcdnxTe1NNt0T66N8D6jxh4kC8UsdzOGaIw==", + "dev": true + }, + "elliptic": { + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz", + "integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==", + "dev": true, + "requires": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "dev": true + } + } + }, + "es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "requires": { + "get-intrinsic": "^1.2.4" + } + }, + "es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" + }, + "esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "requires": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true + }, + "eslint": { + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "eslint-plugin-react-hooks": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", + "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", + "dev": true, + "requires": {} + }, + "eslint-plugin-react-refresh": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.7.tgz", + "integrity": "sha512-yrj+KInFmwuQS2UQcg1SF83ha1tuHC1jMQbRNyuWtlEzzKRDgAl7L4Yp4NlDUZTZNlWvHEzOtJhMi40R7JxcSw==", + "dev": true, + "requires": {} + }, + "eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true + }, + "espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "requires": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + } + }, + "esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + }, + "estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "ethereum-cryptography": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", + "integrity": "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==", + "requires": { + "@noble/curves": "1.4.2", + "@noble/hashes": "1.4.0", + "@scure/bip32": "1.4.0", + "@scure/bip39": "1.3.0" + }, + "dependencies": { + "@noble/curves": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", + "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", + "requires": { + "@noble/hashes": "1.4.0" + } + }, + "@noble/hashes": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", + "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==" + } + } + }, + "ethers": { + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.13.1.tgz", + "integrity": "sha512-hdJ2HOxg/xx97Lm9HdCWk949BfYqYWpyw4//78SiwOLgASyfrNszfMUNB2joKjvGUdwhHfaiMMFFwacVVoLR9A==", + "requires": { + "@adraffy/ens-normalize": "1.10.1", + "@noble/curves": "1.2.0", + "@noble/hashes": "1.3.2", + "@types/node": "18.15.13", + "aes-js": "4.0.0-beta.5", + "tslib": "2.4.0", + "ws": "8.17.1" + }, + "dependencies": { + "tslib": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + } + } + }, + "events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "dependencies": { + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + } + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "fastq": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", + "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "fetch-mock": { + "version": "11.1.5", + "resolved": "https://registry.npmjs.org/fetch-mock/-/fetch-mock-11.1.5.tgz", + "integrity": "sha512-KHmZDnZ1ry0pCTrX4YG5DtThHi0MH+GNI9caESnzX/nMJBrvppUHMvLx47M0WY9oAtKOMiPfZDRpxhlHg89BOA==", + "dev": true, + "requires": { + "@types/glob-to-regexp": "^0.4.4", + "dequal": "^2.0.3", + "glob-to-regexp": "^0.4.1", + "is-subset": "^0.1.1", + "regexparam": "^3.0.0" + } + }, + "fhevmjs": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/fhevmjs/-/fhevmjs-0.6.1.tgz", + "integrity": "sha512-y8G92We5oHHIunA7TykvUR5Sv1jYEQmBfEHJZb6q3GZRPoaHPbmN5QB+R+6NmVk/dch9osbjUnMlGZe7tV4bQA==", + "dev": true, + "requires": { + "bigint-buffer": "^1.1.5", + "commander": "^11.0.0", + "fetch-mock": "^11.1.3", + "keccak": "^3.0.4", + "node-tfhe": "^0.9.1", + "node-tkms": "^0.9.0", + "tfhe": "^0.9.1", + "tkms": "^0.9.0", + "wasm-feature-detect": "^1.8.0" + } + }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true + }, + "fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "requires": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true + }, + "for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "requires": { + "is-callable": "^1.1.3" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, + "fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "optional": true + }, + "function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==" + }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true + }, + "get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "requires": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + } + }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + } + }, + "gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "requires": { + "get-intrinsic": "^1.1.3" + } + }, + "graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "requires": { + "es-define-property": "^1.0.0" + } + }, + "has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==" + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + }, + "has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "requires": { + "has-symbols": "^1.0.3" + } + }, + "hash-base": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.5.tgz", + "integrity": "sha512-vXm0l45VbcHEVlTCzs8M+s0VeYsB2lnlAaThoLKGXr3bE/VWDOelNUnycUPEhKEaXARL2TEFjBOyUiM6+55KBg==", + "dev": true, + "requires": { + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1" + } + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "requires": { + "function-bind": "^1.1.2" + } + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", + "dev": true, + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==", + "dev": true + }, + "idb": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/idb/-/idb-8.0.0.tgz", + "integrity": "sha512-l//qvlAKGmQO31Qn7xdzagVPPaHTxXx199MhrAFuVBTPqydcPYBWjkrbv4Y0ktB+GmWOiwHl237UUOrLmQxLvw==" + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true + }, + "ignore": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", + "dev": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "is-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "requires": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + } + }, + "is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==" + }, + "is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "dev": true, + "requires": { + "hasown": "^2.0.2" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true + }, + "is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "requires": { + "has-tostringtag": "^1.0.0" + } + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-nan": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/is-nan/-/is-nan-1.3.2.tgz", + "integrity": "sha512-E+zBKpQ2t6MEo1VsonYmluk9NxGrbzpeeLC2xIViuO2EjU2xsXsBPwTr3Ykv9l08UYEVEdWeRZNouaZqF6RN0w==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true + }, + "is-subset": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz", + "integrity": "sha512-6Ybun0IkarhmEqxXCNw/C0bna6Zb/TkfUX9UbwJtK6ObwAVCxmAP308WWTHviM/zAqXk05cdhYsUsZeGQh99iw==", + "dev": true + }, + "is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", + "requires": { + "which-typed-array": "^1.1.14" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "isomorphic-timers-promises": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/isomorphic-timers-promises/-/isomorphic-timers-promises-1.0.1.tgz", + "integrity": "sha512-u4sej9B1LPSxTGKB/HiuzvEQnXH0ECYkSVQU39koSwmFAxhlEAFl9RdTvLv4TOTQUgBS5O3O5fwUxk6byBZ+IQ==", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "jsesc": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "dev": true + }, + "json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true + }, + "keccak": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.4.tgz", + "integrity": "sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q==", + "dev": true, + "requires": { + "node-addon-api": "^2.0.0", + "node-gyp-build": "^4.2.0", + "readable-stream": "^3.6.0" + } + }, + "keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "requires": { + "json-buffer": "3.0.1" + } + }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "magic-string": { + "version": "0.30.14", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.14.tgz", + "integrity": "sha512-5c99P1WKTed11ZC0HMJOj6CDIue6F8ySu+bJL+85q1zBEIY8IklrJ1eiKC2NDRh3Ct3FcvmJPyQHb9erXMTJNw==", + "dev": true, + "requires": { + "@jridgewell/sourcemap-codec": "^1.5.0" + } + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "requires": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "dev": true + } + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", + "dev": true + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "nanoid": { + "version": "3.3.8", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", + "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", + "dev": true + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node-addon-api": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", + "integrity": "sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==", + "dev": true + }, + "node-gyp-build": { + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", + "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", + "dev": true + }, + "node-releases": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "dev": true + }, + "node-stdlib-browser": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/node-stdlib-browser/-/node-stdlib-browser-1.3.0.tgz", + "integrity": "sha512-g/koYzOr9Fb1Jc+tHUHlFd5gODjGn48tHexUK8q6iqOVriEgSnd3/1T7myBYc+0KBVze/7F7n65ec9rW6OD7xw==", + "dev": true, + "requires": { + "assert": "^2.0.0", + "browser-resolve": "^2.0.0", + "browserify-zlib": "^0.2.0", + "buffer": "^5.7.1", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "create-require": "^1.1.1", + "crypto-browserify": "^3.11.0", + "domain-browser": "4.22.0", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "isomorphic-timers-promises": "^1.0.1", + "os-browserify": "^0.3.0", + "path-browserify": "^1.0.1", + "pkg-dir": "^5.0.0", + "process": "^0.11.10", + "punycode": "^1.4.1", + "querystring-es3": "^0.2.1", + "readable-stream": "^3.6.0", + "stream-browserify": "^3.0.0", + "stream-http": "^3.2.0", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.1", + "url": "^0.11.4", + "util": "^0.12.4", + "vm-browserify": "^1.0.1" + }, + "dependencies": { + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "dev": true + } + } + }, + "node-tfhe": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/node-tfhe/-/node-tfhe-0.9.1.tgz", + "integrity": "sha512-M2CbUVX4DQneaaK/4fygy9lW0zjOOzM8yGWAgbKGRt/Gd07zaloFEGGHW7dbmUaHo022q1uo7nzxyYhe4UgqCw==", + "dev": true + }, + "node-tkms": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/node-tkms/-/node-tkms-0.9.0.tgz", + "integrity": "sha512-ulhV23okeMW3WYnxzhvf9u87tcXqe64JqUFlvdgu64uKteG8re+zwOjzkOdxvF0xSWQbMtEU96dvcrvQM10PEg==", + "dev": true + }, + "object-inspect": { + "version": "1.13.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", + "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", + "dev": true + }, + "object-is": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz", + "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1" + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "requires": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + } + }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==", + "dev": true + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-asn1": { + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.7.tgz", + "integrity": "sha512-CTM5kuWR3sx9IFamcl5ErfPl6ea/N8IYwiJ+vpeB2g+1iknv7zBl5uPwbMbRVznRVbrNY6lGuDoE5b30grmbqg==", + "dev": true, + "requires": { + "asn1.js": "^4.10.1", + "browserify-aes": "^1.2.0", + "evp_bytestokey": "^1.0.3", + "hash-base": "~3.0", + "pbkdf2": "^3.1.2", + "safe-buffer": "^5.2.1" + } + }, + "path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "pbkdf2": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "dev": true, + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true + }, + "pkg-dir": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-5.0.0.tgz", + "integrity": "sha512-NPE8TDbzl/3YQYY7CSS228s3g2ollTFnc+Qi3tqmqJp9Vg2ovUpixcJEo2HJScN2Ez+kEaal6y70c0ehqJBJeA==", + "dev": true, + "requires": { + "find-up": "^5.0.0" + } + }, + "possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==" + }, + "postcss": { + "version": "8.4.49", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", + "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", + "dev": true, + "requires": { + "nanoid": "^3.3.7", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + } + }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, + "prettier": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.4.1.tgz", + "integrity": "sha512-G+YdqtITVZmOJje6QkXQWzl3fSfMxFwm1tjTyo9exhkmWSqC4Yhd1+lug++IlR2mvRVAxEDDWYkQdeSztajqgg==", + "dev": true + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + }, + "dependencies": { + "bn.js": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.1.tgz", + "integrity": "sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==", + "dev": true + } + } + }, + "punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true + }, + "qs": { + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.1.tgz", + "integrity": "sha512-EJPeIn0CYrGu+hli1xilKAPXODtJ12T0sP63Ijx2/khC2JtuaN3JyNIpvmnkmaEtha9ocbG4A4cMcr+TvqvwQg==", + "dev": true, + "requires": { + "side-channel": "^1.0.6" + } + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==", + "dev": true + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "requires": { + "loose-envify": "^1.1.0" + } + }, + "react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "requires": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + } + }, + "react-refresh": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", + "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", + "dev": true + }, + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "regexparam": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/regexparam/-/regexparam-3.0.0.tgz", + "integrity": "sha512-RSYAtP31mvYLkAHrOlh25pCNQ5hWnT106VukGaaFfuJrZFkGRX5GhUAdPqpSDXxOhA2c4akmRuplv1mRqnBn6Q==", + "dev": true + }, + "resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "requires": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + }, + "reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "rollup": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.27.4.tgz", + "integrity": "sha512-RLKxqHEMjh/RGLsDxAEsaLO3mWgyoU6x9w6n1ikAzet4B3gI2/3yP6PWY2p9QzRTh6MfEIXB3MwsOY0Iv3vNrw==", + "dev": true, + "requires": { + "@rollup/rollup-android-arm-eabi": "4.27.4", + "@rollup/rollup-android-arm64": "4.27.4", + "@rollup/rollup-darwin-arm64": "4.27.4", + "@rollup/rollup-darwin-x64": "4.27.4", + "@rollup/rollup-freebsd-arm64": "4.27.4", + "@rollup/rollup-freebsd-x64": "4.27.4", + "@rollup/rollup-linux-arm-gnueabihf": "4.27.4", + "@rollup/rollup-linux-arm-musleabihf": "4.27.4", + "@rollup/rollup-linux-arm64-gnu": "4.27.4", + "@rollup/rollup-linux-arm64-musl": "4.27.4", + "@rollup/rollup-linux-powerpc64le-gnu": "4.27.4", + "@rollup/rollup-linux-riscv64-gnu": "4.27.4", + "@rollup/rollup-linux-s390x-gnu": "4.27.4", + "@rollup/rollup-linux-x64-gnu": "4.27.4", + "@rollup/rollup-linux-x64-musl": "4.27.4", + "@rollup/rollup-win32-arm64-msvc": "4.27.4", + "@rollup/rollup-win32-ia32-msvc": "4.27.4", + "@rollup/rollup-win32-x64-msvc": "4.27.4", + "@types/estree": "1.0.6", + "fsevents": "~2.3.2" + } + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "requires": { + "loose-envify": "^1.1.0" + } + }, + "semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true + }, + "set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "requires": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", + "dev": true + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + } + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true + }, + "stream-browserify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", + "integrity": "sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==", + "dev": true, + "requires": { + "inherits": "~2.0.4", + "readable-stream": "^3.5.0" + } + }, + "stream-http": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-3.2.0.tgz", + "integrity": "sha512-Oq1bLqisTyK3TSCXpPbT4sdeYNdmyZJv1LxpEm2vu1ZhK89kSE5YXwZc3cWk0MagGaKriBh9mCFbVGtO+vY29A==", + "dev": true, + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "xtend": "^4.0.2" + } + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "tfhe": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/tfhe/-/tfhe-0.9.1.tgz", + "integrity": "sha512-kmtl7KfCCZJaFhm9lUYsTtat+yT0qzOiO6bOidM2Pt7/7jptkbS2/myeGHxb9qi2/aJ30g2joo1euKZPa207tg==", + "dev": true + }, + "timers-browserify": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", + "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", + "dev": true, + "requires": { + "setimmediate": "^1.0.4" + } + }, + "tkms": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/tkms/-/tkms-0.9.0.tgz", + "integrity": "sha512-dSzorTHvIXTYZtn6ACV/iz0GhO/kMRjqGbo3o7JJ3GNbFhsPzbIEtAQ/x+h9nJdwn//VRdsStnOAE0fxUVIGrQ==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "dev": true, + "requires": {} + }, + "tty-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.1.tgz", + "integrity": "sha512-C3TaO7K81YvjCgQH9Q1S3R3P3BtN3RIM8n+OvX4il1K1zgE8ZhI0op7kClgkxtutIE8hQrcrHBXvIheqKUUCxw==", + "dev": true + }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + }, + "typescript": { + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "dev": true + }, + "update-browserslist-db": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", + "dev": true, + "requires": { + "escalade": "^3.2.0", + "picocolors": "^1.1.0" + } + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "url": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.4.tgz", + "integrity": "sha512-oCwdVC7mTuWiPyjLUz/COz5TLk6wgp0RCsN+wHZ2Ekneac9w8uuV0njcbbie2ME+Vs+d6duwmYuR3HgQXs1fOg==", + "dev": true, + "requires": { + "punycode": "^1.4.1", + "qs": "^6.12.3" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", + "dev": true + } + } + }, + "util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "requires": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, + "vite": { + "version": "5.4.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz", + "integrity": "sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==", + "dev": true, + "requires": { + "esbuild": "^0.21.3", + "fsevents": "~2.3.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + } + }, + "vite-plugin-node-polyfills": { + "version": "0.22.0", + "resolved": "https://registry.npmjs.org/vite-plugin-node-polyfills/-/vite-plugin-node-polyfills-0.22.0.tgz", + "integrity": "sha512-F+G3LjiGbG8QpbH9bZ//GSBr9i1InSTkaulfUHFa9jkLqVGORFBoqc2A/Yu5Mmh1kNAbiAeKeK+6aaQUf3x0JA==", + "dev": true, + "requires": { + "@rollup/plugin-inject": "^5.0.5", + "node-stdlib-browser": "^1.2.0" + } + }, + "vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", + "dev": true + }, + "wasm-feature-detect": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/wasm-feature-detect/-/wasm-feature-detect-1.8.0.tgz", + "integrity": "sha512-zksaLKM2fVlnB5jQQDqKXXwYHLQUVH9es+5TOOHwGOVJOCeRBCiPjwSg+3tN2AdTCzjgli4jijCH290kXb/zWQ==", + "dev": true + }, + "web3-errors": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/web3-errors/-/web3-errors-1.3.1.tgz", + "integrity": "sha512-w3NMJujH+ZSW4ltIZZKtdbkbyQEvBzyp3JRn59Ckli0Nz4VMsVq8aF1bLWM7A2kuQ+yVEm3ySeNU+7mSRwx7RQ==", + "requires": { + "web3-types": "^1.10.0" + } + }, + "web3-types": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/web3-types/-/web3-types-1.10.0.tgz", + "integrity": "sha512-0IXoaAFtFc8Yin7cCdQfB9ZmjafrbP6BO0f0KT/khMhXKUpoJ6yShrVhiNpyRBo8QQjuOagsWzwSK2H49I7sbw==" + }, + "web3-validator": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/web3-validator/-/web3-validator-2.0.6.tgz", + "integrity": "sha512-qn9id0/l1bWmvH4XfnG/JtGKKwut2Vokl6YXP5Kfg424npysmtRLe9DgiNBM9Op7QL/aSiaA0TVXibuIuWcizg==", + "requires": { + "ethereum-cryptography": "^2.0.0", + "util": "^0.12.5", + "web3-errors": "^1.2.0", + "web3-types": "^1.6.0", + "zod": "^3.21.4" + } + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "requires": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true + }, + "ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "requires": {} + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true + }, + "zod": { + "version": "3.24.1", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.24.1.tgz", + "integrity": "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==" + } + } +} diff --git a/frontend/package.json b/frontend/package.json index e7c63ad..e13ace3 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,34 +1,41 @@ { - "name": "my-app", - "version": "0.1.0", + "name": "fhevmjs-react-template", "private": true, + "version": "0.0.0", + "type": "module", "scripts": { - "dev": "next dev", - "build": "next build", - "start": "next start", - "lint": "next lint" + "dev": "node scripts/dev.js", + "dev-mocked": "MOCKED=true node scripts/dev.js", + "build": "tsc && vite build", + "lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0", + "preview": "vite preview", + "prettier": "prettier --write \"**/*.{js,json,md,sol,ts,yml}\"", + "prettier:check": "prettier --check \"**/*.{js,json,md,sol,ts,yml}\"" }, "dependencies": { - "@radix-ui/react-dropdown-menu": "^2.1.2", - "class-variance-authority": "^0.7.1", - "clsx": "^2.1.1", - "ethers": "^6.13.4", - "lucide-react": "^0.462.0", - "next": "14.2.16", - "radix-ui": "link:radix-ui", - "react": "^18", - "react-dom": "^18", - "tailwind-merge": "^2.5.5", - "tailwindcss-animate": "^1.0.7" + "ethers": "^6.6.4", + "idb": "^8.0.0", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "web3-validator": "^2.0.6" }, "devDependencies": { - "@types/node": "^20", - "@types/react": "^18", - "@types/react-dom": "^18", - "eslint": "^8", - "eslint-config-next": "14.2.16", - "postcss": "^8", - "tailwindcss": "^3.4.1", - "typescript": "^5" + "@types/react": "^18.3.1", + "@types/react-dom": "^18.3.0", + "@typescript-eslint/eslint-plugin": "^7.13.1", + "@typescript-eslint/parser": "^7.13.1", + "@vitejs/plugin-react": "^4.3.4", + "bigint-buffer": "^1.1.5", + "eslint": "^8.57.0", + "eslint-plugin-react-hooks": "^4.6.2", + "eslint-plugin-react-refresh": "^0.4.7", + "fhevmjs": "^0.6.1", + "prettier": "^3.4.1", + "typescript": "^5.4.5", + "vite": "^5.4.11", + "vite-plugin-node-polyfills": "^0.22.0" + }, + "engines": { + "node": "^20.9.0" } } diff --git a/frontend/public/vite.svg b/frontend/public/vite.svg new file mode 100644 index 0000000..e7b8dfb --- /dev/null +++ b/frontend/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/scripts/dev.js b/frontend/scripts/dev.js new file mode 100644 index 0000000..01e2308 --- /dev/null +++ b/frontend/scripts/dev.js @@ -0,0 +1,23 @@ +import { build, preview } from 'vite'; + +(async () => { + try { + await preview({ + BASE_URL: '/', + MODE: 'production', + DEV: false, + PROD: true, + }); + console.log('Preview server is running...'); + console.log('Listening on http://localhost:4173\n'); + + const watcher = await build({ + build: { + watch: {}, + }, + }); + console.log('Build in watch mode is running...'); + } catch (err) { + console.error('Error:', err); + } +})(); diff --git a/frontend/src/App.css b/frontend/src/App.css new file mode 100644 index 0000000..432f62a --- /dev/null +++ b/frontend/src/App.css @@ -0,0 +1,10 @@ +#root { + box-sizing: border-box; + max-width: 90vw; + margin: 0 auto; + text-align: center; +} + +.read-the-docs { + color: #888; +} diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx new file mode 100644 index 0000000..7d048f9 --- /dev/null +++ b/frontend/src/App.tsx @@ -0,0 +1,37 @@ +import { useEffect, useState } from 'react'; +import { Devnet } from './components/Devnet'; +import { init } from './fhevmjs'; +import './App.css'; +import { Connect } from './components/Connect'; + +function App() { + const [isInitialized, setIsInitialized] = useState(false); + + useEffect(() => { + init() + .then(() => { + setIsInitialized(true); + }) + .catch(() => setIsInitialized(false)); + }, []); + + if (!isInitialized) return null; + + return ( + <> +

Confidential ERC20 dApp

+ + {(account, provider) => ( + + )} + +

+ + See the documentation for more information + +

+ + ); +} + +export default App; diff --git a/frontend/src/components/Connect/Connect.css b/frontend/src/components/Connect/Connect.css new file mode 100644 index 0000000..674865c --- /dev/null +++ b/frontend/src/components/Connect/Connect.css @@ -0,0 +1,11 @@ +.Connect__account { + width: 100%; + max-width: 300px; + text-overflow: ellipsis; + overflow: hidden; + margin: 0 auto; +} + +.Connect__wrongNetwork { + color: #ff0000; +} diff --git a/frontend/src/components/Connect/Connect.tsx b/frontend/src/components/Connect/Connect.tsx new file mode 100644 index 0000000..fe8ec37 --- /dev/null +++ b/frontend/src/components/Connect/Connect.tsx @@ -0,0 +1,152 @@ +import React, { useCallback, useEffect, useMemo, useState } from 'react'; +import { BrowserProvider } from 'ethers'; + +import './Connect.css'; +import { Eip1193Provider } from 'ethers'; +import { createFhevmInstance } from '../../fhevmjs'; + +const AUTHORIZED_CHAIN_ID = ['0xaa36a7', '0x2328', '0x7a69']; + +export const Connect: React.FC<{ + children: (account: string, provider: any) => React.ReactNode; +}> = ({ children }) => { + const [connected, setConnected] = useState(false); + const [validNetwork, setValidNetwork] = useState(false); + const [account, setAccount] = useState(''); + const [error, setError] = useState(null); + const [provider, setProvider] = useState(null); + const [loading, setLoading] = useState(true); + + const refreshAccounts = (accounts: string[]) => { + setAccount(accounts[0] || ''); + setConnected(accounts.length > 0); + }; + + const hasValidNetwork = async (): Promise => { + const currentChainId: string = ( + await window.ethereum.request({ + method: 'eth_chainId', + }) + ).toLowerCase(); + + return import.meta.env.MOCKED + ? currentChainId === AUTHORIZED_CHAIN_ID[2] + : currentChainId === AUTHORIZED_CHAIN_ID[0]; + }; + + const refreshNetwork = useCallback(async () => { + if (await hasValidNetwork()) { + setValidNetwork(true); + setLoading(true); + const load = async () => { + await createFhevmInstance(); + setLoading(false); + }; + window.requestAnimationFrame(load); + } else { + setValidNetwork(false); + } + }, []); + + const refreshProvider = (eth: Eip1193Provider) => { + const p = new BrowserProvider(eth); + setProvider(p); + return p; + }; + + useEffect(() => { + const eth = window.ethereum; + if (!eth) { + setError('No wallet has been found'); + return; + } + + const p = refreshProvider(eth); + + p.send('eth_accounts', []) + .then(async (accounts: string[]) => { + refreshAccounts(accounts); + await refreshNetwork(); + }) + .catch(() => { + // Do nothing + }); + eth.on('accountsChanged', refreshAccounts); + eth.on('chainChanged', refreshNetwork); + }, []); + + const connect = async () => { + if (!provider) { + return; + } + const accounts: string[] = await provider.send('eth_requestAccounts', []); + + if (accounts.length > 0) { + setAccount(accounts[0]); + setConnected(true); + if (!(await hasValidNetwork())) { + await switchNetwork(); + } + } + }; + + const switchNetwork = useCallback(async () => { + try { + await window.ethereum.request({ + method: 'wallet_switchEthereumChain', + params: [ + { chainId: AUTHORIZED_CHAIN_ID[import.meta.env.MOCKED ? 2 : 0] }, + ], + }); + } catch (e) { + console.error( + `No ${import.meta.env.MOCKED ? 'Hardhat' : 'Sepolia'} chain configured`, + ); + } + }, []); + + const child = useMemo(() => { + if (!account || !provider) { + return null; + } + + if (!validNetwork) { + return ( +
+

You're not on the correct network

+

+ +

+
+ ); + } + + if (loading) { + return

Loading...

; + } + + return children(account, provider); + }, [account, provider, children, validNetwork, loading]); + + if (error) { + return

No wallet has been found.

; + } + + const connectInfos = ( +
+ {!connected && } + {connected && ( +
Connected with {account}
+ )} +
+ ); + + return ( + <> + {connectInfos} +
{child}
+ + ); +}; diff --git a/frontend/src/components/Connect/index.ts b/frontend/src/components/Connect/index.ts new file mode 100644 index 0000000..75ef3b2 --- /dev/null +++ b/frontend/src/components/Connect/index.ts @@ -0,0 +1 @@ +export * from './Connect'; diff --git a/frontend/src/components/Devnet/Devnet.css b/frontend/src/components/Devnet/Devnet.css new file mode 100644 index 0000000..4b3c250 --- /dev/null +++ b/frontend/src/components/Devnet/Devnet.css @@ -0,0 +1,12 @@ +.Devnet__dd { + margin: 0; +} + +.Devnet__pre { + white-space: break-spaces; + word-wrap: break-word; +} + +.Devnet__title { + font-weight: bold; +} diff --git a/frontend/src/components/Devnet/Devnet.tsx b/frontend/src/components/Devnet/Devnet.tsx new file mode 100644 index 0000000..6aabf2e --- /dev/null +++ b/frontend/src/components/Devnet/Devnet.tsx @@ -0,0 +1,276 @@ +import { useEffect, useState } from 'react'; +import { getInstance } from '../../fhevmjs'; +import './Devnet.css'; +import { Eip1193Provider, ZeroAddress } from 'ethers'; +import { ethers } from 'ethers'; + +import { reencryptEuint64 } from '../../../../hardhat/test/reencrypt.ts'; + +const toHexString = (bytes: Uint8Array) => + '0x' + + bytes.reduce((str, byte) => str + byte.toString(16).padStart(2, '0'), ''); + +export type DevnetProps = { + account: string; + provider: Eip1193Provider; +}; + +export const Devnet = ({ account, provider }: DevnetProps) => { + const [contractAddress, setContractAddress] = useState(ZeroAddress); + + const [handleBalance, setHandleBalance] = useState('0'); + const [decryptedBalance, setDecryptedBalance] = useState('???'); + + const [handles, setHandles] = useState([]); + const [encryption, setEncryption] = useState(); + + const [inputValue, setInputValue] = useState(''); // Track the input + const [chosenValue, setChosenValue] = useState('0'); // Track the confirmed value + + const [inputValueAddress, setInputValueAddress] = useState(''); + const [chosenAddress, setChosenAddress] = useState('0x'); + const [errorMessage, setErrorMessage] = useState(''); + + const [decryptedSecret, setDecryptedResult] = useState('???'); + const [counter, setCounter] = useState(0); // useful trick to make the refresh of decryption state work, otherwise contract call will not work correctly (because provider's state won't be updated without a React re-rendering) + + useEffect(() => { + const loadData = async () => { + try { + // Conditional import based on MOCKED environment variable + let MyConfidentialERC20; + if (!import.meta.env.MOCKED) { + MyConfidentialERC20 = await import( + '@deployments/sepolia/MyConfidentialERC20.json' + ); + console.log( + `Using ${MyConfidentialERC20.address} for the token address on Sepolia`, + ); + } else { + MyConfidentialERC20 = await import( + '@deployments/localhost/MyConfidentialERC20.json' + ); + console.log( + `Using ${MyConfidentialERC20.address} for the token address on Hardhat Local Node`, + ); + } + + setContractAddress(MyConfidentialERC20.address); + } catch (error) { + console.error( + 'Error loading data - you probably forgot to deploy the token contract before running the front-end server:', + error, + ); + } + }; + + loadData(); + }, []); + + const handleConfirmAmount = () => { + setChosenValue(inputValue); + }; + + const handleConfirmAddress = () => { + const trimmedValue = inputValueAddress.trim().toLowerCase(); + if (ethers.isAddress(trimmedValue)) { + // getAddress returns the checksummed address + const checksummedAddress = ethers.getAddress(trimmedValue); + setChosenAddress(checksummedAddress); + setErrorMessage(''); + } else { + setChosenAddress('0x'); + setErrorMessage('Invalid Ethereum address.'); + } + }; + + const instance = getInstance(); + + const getHandleBalance = async () => { + if (contractAddress != ZeroAddress) { + const contract = new ethers.Contract( + contractAddress, + ['function balanceOf(address) view returns (uint256)'], + provider, + ); + const handleBalance = await contract.balanceOf(account); + setHandleBalance(handleBalance.toString()); + setDecryptedBalance('???'); + } + }; + + useEffect(() => { + getHandleBalance(); + }, [account, provider, contractAddress]); + + const encrypt = async (val: bigint) => { + const now = Date.now(); + try { + const result = await instance + .createEncryptedInput(contractAddress, account) + .add64(val) + .encrypt(); + console.log(`Took ${(Date.now() - now) / 1000}s`); + setHandles(result.handles); + setEncryption(result.inputProof); + } catch (e) { + console.error('Encryption error:', e); + console.log(Date.now() - now); + } + }; + + const decrypt = async () => { + const signer = await provider.getSigner(); + try { + const clearBalance = await reencryptEuint64( + signer, + instance, + BigInt(handleBalance), + contractAddress, + ); + setDecryptedBalance(clearBalance.toString()); + } catch (error) { + if (error === 'Handle is not initialized') { + // if handle is uninitialized - i.e equal to 0 - we know for sure that the balance is null + setDecryptedBalance('0'); + } else { + throw error; + } + } + }; + + const transferToken = async () => { + const contract = new ethers.Contract( + contractAddress, + ['function transfer(address,bytes32,bytes) external returns (bool)'], + provider, + ); + const signer = await provider.getSigner(); + const tx = await contract + .connect(signer) + .transfer( + chosenAddress, + toHexString(handles[0]), + toHexString(encryption), + ); + await tx.wait(); + await getHandleBalance(); + }; + + const decryptSecret = async () => { + const contract = new ethers.Contract( + contractAddress, + ['function requestSecret() external'], + provider, + ); + const signer = await provider.getSigner(); + const tx = await contract.connect(signer).requestSecret(); + await tx.wait(); + }; + + const refreshSecret = async () => { + setCounter(counter + 1); + const contract = new ethers.Contract( + contractAddress, + ['function revealedSecret() view returns(uint64)'], + provider, + ); + const revealedSecret = await contract.revealedSecret(); + const revealedSecretString = + revealedSecret === 0n ? '???' : revealedSecret.toString(); + setDecryptedResult(revealedSecretString); + }; + + return ( +
+
+
My encrypted balance is:
+
{handleBalance.toString()}
+ + +
+ My decrypted private balance is: {decryptedBalance.toString()} +
+ +
Chose an amount to transfer:
+ +
+ setInputValue(e.target.value)} + placeholder="Enter a number" + />{' '} + + {chosenValue !== null && ( +
+

You chose: {chosenValue}

+
+ )} +
+ + +
+ This is an encryption of {chosenValue}: +
+
+
+            Handle: {handles.length ? toHexString(handles[0]) : ''}
+          
+
+            Input Proof: {encryption ? toHexString(encryption) : ''}
+          
+
+ +
+ setInputValueAddress(e.target.value)} + placeholder="Receiver address" + /> + {' '} + {chosenAddress && ( +
+

Chosen Address For Receiver: {chosenAddress}

+
+ )} + {errorMessage && ( +
+

{errorMessage}

+
+ )} +
+ +
+ {chosenAddress !== '0x' && encryption && encryption.length > 0 && ( + + )} +
+ +
+ +
+
+
+ The decrypted secret value is: {decryptedSecret}{' '} + +
+
+
+
+ ); +}; diff --git a/frontend/src/components/Devnet/Devnet.tsx.bak b/frontend/src/components/Devnet/Devnet.tsx.bak new file mode 100644 index 0000000..9d22f2a --- /dev/null +++ b/frontend/src/components/Devnet/Devnet.tsx.bak @@ -0,0 +1,102 @@ +import { useEffect, useState } from 'react'; +import { getInstance } from '../../fhevmjs'; +import './Devnet.css'; +import { Eip1193Provider } from 'ethers'; +import { ethers } from 'ethers'; + +import MyConfidentialERC20 from '../../../../deployments/sepolia/MyConfidentialERC20.json'; +import { reencryptEuint64 } from '../../../../test/reencrypt.ts'; + +const toHexString = (bytes: Uint8Array) => + bytes.reduce((str, byte) => str + byte.toString(16).padStart(2, '0'), ''); + +export type DevnetProps = { + account: string; + provider: Eip1193Provider; +}; + +const CONTRACT_ADDRESS = MyConfidentialERC20.address; + +export const Devnet = ({ account, provider }: DevnetProps) => { + const [handleBalance, setHandleBalance] = useState('0'); + const [decryptedBalance, setDecryptedBalance] = useState('???'); + + const [handles, setHandles] = useState([]); + const [encryption, setEncryption] = useState(); + const instance = getInstance(); + + useEffect(() => { + const getHandleBalance = async () => { + const contract = new ethers.Contract( + CONTRACT_ADDRESS, + // Minimal ABI for balanceOf + ['function balanceOf(address) view returns (uint256)'], + provider, + ); + const handleBalance = await contract.balanceOf(account); + setHandleBalance(handleBalance); + }; + getHandleBalance(); + }, [account, provider]); + + const encrypt = async (val: number) => { + const now = Date.now(); + try { + const result = await instance + .createEncryptedInput(CONTRACT_ADDRESS, account) + .add64(val) + .encrypt(); + + console.log(`Took ${(Date.now() - now) / 1000}s`); + setHandles(result.handles); + setEncryption(result.inputProof); + } catch (e) { + console.error('Encryption error:', e); + console.log(Date.now() - now); + } + }; + + const decrypt = async () => { + const signer = await provider.getSigner(); + try { + const clearBalance = await reencryptEuint64( + signer, + instance, + BigInt(handleBalance), + CONTRACT_ADDRESS, + ); + setDecryptedBalance(clearBalance.toString()); + } catch (error) { + if (error === 'Handle is not initialized') { + // if handle is uninitialized - i.e equal to 0 - we know for sure that the balance is null + setDecryptedBalance('0'); + } else { + throw error; + } + } + }; + + return ( +
+
+
My encrypted balance is:
+
{handleBalance.toString()}
+ + + + +
This is an encryption of 1337:
+
+
+            Handle: {handles.length ? toHexString(handles[0]) : ''}
+          
+
+            Input Proof: {encryption ? toHexString(encryption) : ''}
+          
+
+
+
+ ); +}; diff --git a/frontend/src/components/Devnet/index.ts b/frontend/src/components/Devnet/index.ts new file mode 100644 index 0000000..bcc59e5 --- /dev/null +++ b/frontend/src/components/Devnet/index.ts @@ -0,0 +1 @@ +export * from './Devnet'; diff --git a/frontend/src/fhevmStorage.ts b/frontend/src/fhevmStorage.ts new file mode 100644 index 0000000..2eda65e --- /dev/null +++ b/frontend/src/fhevmStorage.ts @@ -0,0 +1,75 @@ +import { openDB, DBSchema, IDBPDatabase } from 'idb'; + +interface PublicParamsDB extends DBSchema { + publicKeyStore: { + key: string; + value: { + acl: string; + value: { publicKeyId: string; publicKey: Uint8Array }; + }; + }; + paramsStore: { + key: string; + value: { + acl: string; + value: { publicParamsId: string; publicParams: Uint8Array }; + }; + }; +} + +const dbPromise: Promise> = openDB( + 'fhevm', + 1, + { + upgrade(db) { + if (!db.objectStoreNames.contains('paramsStore')) { + db.createObjectStore('paramsStore', { keyPath: 'acl' }); + } + if (!db.objectStoreNames.contains('publicKeyStore')) { + db.createObjectStore('publicKeyStore', { keyPath: 'acl' }); + } + }, + }, +); + +export async function storePublicParams( + acl: string, + value: { publicParamsId: string; publicParams: Uint8Array }, +): Promise { + const db = await dbPromise; + await db.put('paramsStore', { acl, value }); + console.log(`Stored public params for: ${acl}`); +} + +export async function getPublicParams( + acl: string, +): Promise<{ publicParamsId: string; publicParams: Uint8Array } | null> { + const db = await dbPromise; + try { + const result = await db.get('paramsStore', acl); + return result ? result.value : null; + } catch (e) { + return null; + } +} + +export async function storePublicKey( + acl: string, + value: { publicKeyId: string; publicKey: Uint8Array }, +): Promise { + const db = await dbPromise; + await db.put('publicKeyStore', { acl, value }); + console.log(`Stored public key for: ${acl}`); +} + +export async function getPublicKey( + acl: string, +): Promise<{ publicKeyId: string; publicKey: Uint8Array } | null> { + const db = await dbPromise; + try { + const result = await db.get('publicKeyStore', acl); + return result ? result.value : null; + } catch (e) { + return null; + } +} diff --git a/frontend/src/fhevmjs.ts b/frontend/src/fhevmjs.ts new file mode 100644 index 0000000..93939f0 --- /dev/null +++ b/frontend/src/fhevmjs.ts @@ -0,0 +1,108 @@ +import { isAddress } from 'ethers'; +import { + initFhevm, + createInstance, + FhevmInstance, + createEIP712, + generateKeypair, +} from 'fhevmjs'; +import { + getPublicKey, + getPublicParams, + storePublicKey, + storePublicParams, +} from './fhevmStorage'; + +import { + reencryptRequestMocked, + createEncryptedInputMocked, +} from './fhevmjsMocked'; + +const ACL_ADDRESS: string = import.meta.env.VITE_ACL_ADDRESS; +const MOCKED: string = import.meta.env.MOCKED; + +export type Keypair = { + publicKey: string; + privateKey: string; + signature: string; +}; + +type Keypairs = { + [key: string]: { + [key: string]: Keypair; + }; +}; + +export const init = async () => { + await initFhevm({ thread: navigator.hardwareConcurrency }); +}; + +let instancePromise: Promise; +let instance: FhevmInstance; + +const keypairs: Keypairs = {}; + +export const createFhevmInstance = async () => { + if (instancePromise) return instancePromise; + const storedPublicKey = await getPublicKey(ACL_ADDRESS); + const publicKey = storedPublicKey?.publicKey; + const publicKeyId = storedPublicKey?.publicKeyId; + const storedPublicParams = await getPublicParams(ACL_ADDRESS); + const publicParams = storedPublicParams + ? { + '2048': storedPublicParams, + } + : null; + instancePromise = createInstance({ + network: window.ethereum, + aclContractAddress: ACL_ADDRESS, + kmsContractAddress: import.meta.env.VITE_KMS_ADDRESS, + gatewayUrl: import.meta.env.VITE_GATEWAY_URL, + publicKey, + publicKeyId, + publicParams, + }); + instance = await instancePromise; + const pp = instance.getPublicParams(2048); + if (pp) { + await storePublicParams(ACL_ADDRESS, pp); + } + const pk = instance.getPublicKey(); + if (pk) { + await storePublicKey(ACL_ADDRESS, pk); + } +}; + +export const setKeypair = ( + contractAddress: string, + userAddress: string, + keypair: Keypair, +) => { + if (!isAddress(contractAddress) || !isAddress(userAddress)) return; + keypairs[userAddress][contractAddress] = keypair; +}; + +export const getKeypair = ( + contractAddress: string, + userAddress: string, +): Keypair | null => { + if (!isAddress(contractAddress) || !isAddress(userAddress)) return null; + return keypairs[userAddress] + ? keypairs[userAddress][contractAddress] || null + : null; +}; + +export const getInstance = () => { + if (MOCKED) { + const instanceMocked = { + reencrypt: reencryptRequestMocked, + createEncryptedInput: createEncryptedInputMocked, + getPublicKey: () => '0xFFAA44433', + generateKeypair: generateKeypair, + createEIP712: createEIP712(31337), + }; + return instanceMocked; + } else { + return instance; + } +}; diff --git a/frontend/src/fhevmjsMocked.ts b/frontend/src/fhevmjsMocked.ts new file mode 100644 index 0000000..9e37e64 --- /dev/null +++ b/frontend/src/fhevmjsMocked.ts @@ -0,0 +1,380 @@ +import { ethers, BrowserProvider } from 'ethers'; +import { isAddress } from 'web3-validator'; +import { toBigIntBE } from 'bigint-buffer'; + +export const reencryptRequestMocked = async ( + handle: bigint, + privateKey: string, + publicKey: string, + signature: string, + contractAddress: string, + userAddress: string, +) => { + // Signature checking: + const domain = { + name: 'Authorization token', + version: '1', + chainId: 31337, + verifyingContract: contractAddress, + }; + const types = { + Reencrypt: [{ name: 'publicKey', type: 'bytes' }], + }; + const value = { + publicKey: `0x${publicKey}`, + }; + const signerAddress = ethers.verifyTypedData( + domain, + types, + value, + `0x${signature}`, + ); + const normalizedSignerAddress = ethers.getAddress(signerAddress); + const normalizedUserAddress = ethers.getAddress(userAddress); + if (normalizedSignerAddress !== normalizedUserAddress) { + throw new Error('Invalid EIP-712 signature!'); + } + + // ACL checking + const provider = new BrowserProvider(window.ethereum); + const acl = new ethers.Contract( + import.meta.env.VITE_ACL_ADDRESS, + ['function persistAllowed(uint256,address) external view returns (bool)'], + provider, + ); + + const userAllowed = await acl.persistAllowed(handle, userAddress); + + const contractAllowed = await acl.persistAllowed(handle, contractAddress); + const isAllowed = userAllowed && contractAllowed; + if (!isAllowed) { + throw new Error('User is not authorized to reencrypt this handle!'); + } + if (userAddress === contractAddress) { + throw new Error( + 'userAddress should not be equal to contractAddress when requesting reencryption!', + ); + } + return BigInt(await getClearText(handle)); +}; + +const getClearText = async (handleBigInt: bigint): Promise => { + const handle = handleBigInt.toString(); + const { status, result, message } = await fetch( + 'http://localhost:3000/get-clear-text', + { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ handle }), + }, + ).then((res) => res.json()); + + if (status === 'error') throw new Error(message); + return result; +}; + +const ENCRYPTION_TYPES = { + 2: 0, // ebool takes 2 bits + 4: 1, + 8: 2, + 16: 3, + 32: 4, + 64: 5, + 128: 6, + 160: 7, + 256: 8, + 512: 9, + 1024: 10, + 2048: 11, +}; + +const sum = (arr: number[]) => arr.reduce((acc, val) => acc + val, 0); + +function bytesToBigInt(byteArray: Uint8Array): bigint { + if (!byteArray || byteArray?.length === 0) { + return BigInt(0); + } + const buffer = Buffer.from(byteArray); + const result = toBigIntBE(buffer); + return result; +} + +const checkEncryptedValue = (value: number | bigint, bits: number) => { + if (value == null) throw new Error('Missing value'); + let limit; + if (bits >= 8) { + limit = BigInt( + `0x${new Array(bits / 8).fill(null).reduce((v) => `${v}ff`, '')}`, + ); + } else { + limit = BigInt(2 ** bits - 1); + } + if (typeof value !== 'number' && typeof value !== 'bigint') + throw new Error('Value must be a number or a bigint.'); + if (value > limit) { + throw new Error( + `The value exceeds the limit for ${bits}bits integer (${limit.toString()}).`, + ); + } +}; + +export const createEncryptedInputMocked = ( + contractAddress: string, + userAddress: string, +) => { + if (!isAddress(contractAddress)) { + throw new Error('Contract address is not a valid address.'); + } + + if (!isAddress(userAddress)) { + throw new Error('User address is not a valid address.'); + } + + const values: bigint[] = []; + const bits: (keyof typeof ENCRYPTION_TYPES)[] = []; + return { + addBool(value: boolean | number | bigint) { + if (value == null) throw new Error('Missing value'); + if ( + typeof value !== 'boolean' && + typeof value !== 'number' && + typeof value !== 'bigint' + ) + throw new Error('The value must be a boolean, a number or a bigint.'); + if ( + (typeof value !== 'bigint' || typeof value !== 'number') && + Number(value) > 1 + ) + throw new Error('The value must be 1 or 0.'); + values.push(BigInt(value)); + bits.push(2); // ebool takes 2 bits instead of one: only exception in TFHE-rs + if (sum(bits) > 2048) + throw Error( + 'Packing more than 2048 bits in a single input ciphertext is unsupported', + ); + if (bits.length > 256) + throw Error( + 'Packing more than 256 variables in a single input ciphertext is unsupported', + ); + return this; + }, + add4(value: number | bigint) { + checkEncryptedValue(value, 4); + values.push(BigInt(value)); + bits.push(4); + if (sum(bits) > 2048) + throw Error( + 'Packing more than 2048 bits in a single input ciphertext is unsupported', + ); + if (bits.length > 256) + throw Error( + 'Packing more than 256 variables in a single input ciphertext is unsupported', + ); + return this; + }, + add8(value: number | bigint) { + checkEncryptedValue(value, 8); + values.push(BigInt(value)); + bits.push(8); + if (sum(bits) > 2048) + throw Error( + 'Packing more than 2048 bits in a single input ciphertext is unsupported', + ); + if (bits.length > 256) + throw Error( + 'Packing more than 256 variables in a single input ciphertext is unsupported', + ); + return this; + }, + add16(value: number | bigint) { + checkEncryptedValue(value, 16); + values.push(BigInt(value)); + bits.push(16); + if (sum(bits) > 2048) + throw Error( + 'Packing more than 2048 bits in a single input ciphertext is unsupported', + ); + if (bits.length > 256) + throw Error( + 'Packing more than 256 variables in a single input ciphertext is unsupported', + ); + return this; + }, + add32(value: number | bigint) { + checkEncryptedValue(value, 32); + values.push(BigInt(value)); + bits.push(32); + if (sum(bits) > 2048) + throw Error( + 'Packing more than 2048 bits in a single input ciphertext is unsupported', + ); + if (bits.length > 256) + throw Error( + 'Packing more than 256 variables in a single input ciphertext is unsupported', + ); + return this; + }, + add64(value: number | bigint) { + checkEncryptedValue(value, 64); + values.push(BigInt(value)); + bits.push(64); + if (sum(bits) > 2048) + throw Error( + 'Packing more than 2048 bits in a single input ciphertext is unsupported', + ); + if (bits.length > 256) + throw Error( + 'Packing more than 256 variables in a single input ciphertext is unsupported', + ); + return this; + }, + add128(value: number | bigint) { + checkEncryptedValue(value, 128); + values.push(BigInt(value)); + bits.push(128); + if (sum(bits) > 2048) + throw Error( + 'Packing more than 2048 bits in a single input ciphertext is unsupported', + ); + if (bits.length > 256) + throw Error( + 'Packing more than 256 variables in a single input ciphertext is unsupported', + ); + return this; + }, + addAddress(value: string) { + if (!isAddress(value)) { + throw new Error('The value must be a valid address.'); + } + values.push(BigInt(value)); + bits.push(160); + if (sum(bits) > 2048) + throw Error( + 'Packing more than 2048 bits in a single input ciphertext is unsupported', + ); + if (bits.length > 256) + throw Error( + 'Packing more than 256 variables in a single input ciphertext is unsupported', + ); + return this; + }, + add256(value: number | bigint) { + checkEncryptedValue(value, 256); + values.push(BigInt(value)); + bits.push(256); + if (sum(bits) > 2048) + throw Error( + 'Packing more than 2048 bits in a single input ciphertext is unsupported', + ); + if (bits.length > 256) + throw Error( + 'Packing more than 256 variables in a single input ciphertext is unsupported', + ); + return this; + }, + addBytes64(value: Uint8Array) { + if (value.length !== 64) + throw Error( + 'Uncorrect length of input Uint8Array, should be 64 for an ebytes64', + ); + const bigIntValue = bytesToBigInt(value); + checkEncryptedValue(bigIntValue, 512); + values.push(bigIntValue); + bits.push(512); + if (sum(bits) > 2048) + throw Error( + 'Packing more than 2048 bits in a single input ciphertext is unsupported', + ); + if (bits.length > 256) + throw Error( + 'Packing more than 256 variables in a single input ciphertext is unsupported', + ); + return this; + }, + addBytes128(value: Uint8Array) { + if (value.length !== 128) + throw Error( + 'Uncorrect length of input Uint8Array, should be 128 for an ebytes128', + ); + const bigIntValue = bytesToBigInt(value); + checkEncryptedValue(bigIntValue, 1024); + values.push(bigIntValue); + bits.push(1024); + if (sum(bits) > 2048) + throw Error( + 'Packing more than 2048 bits in a single input ciphertext is unsupported', + ); + if (bits.length > 256) + throw Error( + 'Packing more than 256 variables in a single input ciphertext is unsupported', + ); + return this; + }, + addBytes256(value: Uint8Array) { + if (value.length !== 256) + throw Error( + 'Uncorrect length of input Uint8Array, should be 256 for an ebytes256', + ); + const bigIntValue = bytesToBigInt(value); + checkEncryptedValue(bigIntValue, 2048); + values.push(bigIntValue); + bits.push(2048); + if (sum(bits) > 2048) + throw Error( + 'Packing more than 2048 bits in a single input ciphertext is unsupported', + ); + if (bits.length > 256) + throw Error( + 'Packing more than 256 variables in a single input ciphertext is unsupported', + ); + return this; + }, + getValues() { + return values; + }, + getBits() { + return bits; + }, + resetValues() { + values.length = 0; + bits.length = 0; + return this; + }, + async encrypt() { + const res = await encryptValues( + values, + bits, + userAddress, + contractAddress, + ); + + return res; + }, + }; +}; + +const encryptValues = async ( + values: bigint[], + bits: (keyof typeof ENCRYPTION_TYPES)[], + userAddress: string, + contractAddress: string, +): Promise<{ handles: Uint8Array[]; inputProof: Uint8Array }> => { + const response = await fetch('http://localhost:3000/encrypt', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ + values: values.map((v) => v.toString()), + bits, + userAddress, + contractAddress, + }), + }); + + const data = await response.json(); + if (data.status === 'error') throw new Error(data.message); + + return { + handles: data.handles.map((h) => ethers.getBytes(h)), + inputProof: ethers.getBytes(data.inputProof), + }; +}; diff --git a/frontend/src/index.css b/frontend/src/index.css new file mode 100644 index 0000000..2c3fac6 --- /dev/null +++ b/frontend/src/index.css @@ -0,0 +1,69 @@ +:root { + font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; + line-height: 1.5; + font-weight: 400; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + -webkit-text-size-adjust: 100%; +} + +a { + font-weight: 500; + color: #646cff; + text-decoration: inherit; +} +a:hover { + color: #535bf2; +} + +body { + margin: 0; + display: flex; + place-items: center; + min-width: 320px; + min-height: 100vh; +} + +h1 { + font-size: 3.2em; + line-height: 1.1; +} + +button { + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + font-family: inherit; + background-color: #1a1a1a; + cursor: pointer; + transition: border-color 0.25s; +} +button:hover { + border-color: #646cff; +} +button:focus, +button:focus-visible { + outline: 4px auto -webkit-focus-ring-color; +} + +@media (prefers-color-scheme: light) { + :root { + color: #213547; + background-color: #ffffff; + } + a:hover { + color: #747bff; + } + button { + background-color: #f9f9f9; + } +} diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx new file mode 100644 index 0000000..93db379 --- /dev/null +++ b/frontend/src/main.tsx @@ -0,0 +1,10 @@ +import React from 'react'; +import ReactDOM from 'react-dom/client'; +import App from './App.tsx'; +import './index.css'; + +ReactDOM.createRoot(document.getElementById('root')!).render( + + + +); diff --git a/frontend/src/vite-env.d.ts b/frontend/src/vite-env.d.ts new file mode 100644 index 0000000..e7bd798 --- /dev/null +++ b/frontend/src/vite-env.d.ts @@ -0,0 +1,7 @@ +/// + +interface Window { + ethereum: import('ethers').Eip1193Provider & { + on: (event: string, cb: (param: any) => any) => void; + }; +} diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index e7ff90f..a7fc6fb 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -1,26 +1,25 @@ { "compilerOptions": { - "lib": ["dom", "dom.iterable", "esnext"], - "allowJs": true, + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", "skipLibCheck": true, - "strict": true, - "noEmit": true, - "esModuleInterop": true, - "module": "esnext", + + /* Bundler mode */ "moduleResolution": "bundler", + "allowImportingTsExtensions": true, "resolveJsonModule": true, "isolatedModules": true, - "jsx": "preserve", - "incremental": true, - "plugins": [ - { - "name": "next" - } - ], - "paths": { - "@/*": ["./*"] - } + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], - "exclude": ["node_modules"] + "include": ["src"], + "references": [{ "path": "./tsconfig.node.json" }] } diff --git a/frontend/tsconfig.node.json b/frontend/tsconfig.node.json new file mode 100644 index 0000000..42872c5 --- /dev/null +++ b/frontend/tsconfig.node.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "composite": true, + "skipLibCheck": true, + "module": "ESNext", + "moduleResolution": "bundler", + "allowSyntheticDefaultImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts new file mode 100644 index 0000000..84a50c0 --- /dev/null +++ b/frontend/vite.config.ts @@ -0,0 +1,36 @@ +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; +import { nodePolyfills } from 'vite-plugin-node-polyfills'; +import path from 'path'; + +const workerImportMetaUrlRE = + /\bnew\s+(?:Worker|SharedWorker)\s*\(\s*(new\s+URL\s*\(\s*('[^']+'|"[^"]+"|`[^`]+`)\s*,\s*import\.meta\.url\s*\))/g; + +// https://vitejs.dev/config/ +export default defineConfig({ + assetsInclude: ['**/*.bin'], + plugins: [react(), nodePolyfills()], + define: { + 'import.meta.env.MOCKED': process.env.MOCKED === 'true', + }, + resolve: { + alias: { + '@deployments': path.resolve(__dirname, '../hardhat/deployments'), + }, + }, + server: { + port: 9000, + headers: { + 'Cross-Origin-Opener-Policy': 'same-origin', + 'Cross-Origin-Embedder-Policy': 'require-corp', + }, + }, + worker: { + format: 'es', + rollupOptions: { + output: { + entryFileNames: '[name].js', + }, + }, + }, +}); diff --git a/hardhat/test/decIdentity/passportID.ts b/hardhat/test/decIdentity/passportID.ts index 9f2c6a1..c28090c 100644 --- a/hardhat/test/decIdentity/passportID.ts +++ b/hardhat/test/decIdentity/passportID.ts @@ -6,7 +6,7 @@ import type { FhevmInstance } from "fhevmjs"; import type { Diploma, EmployerClaim, IdMapping, PassportID } from "../../types"; import { createInstance } from "../instance"; -import { reencryptEbool, reencryptEbytes64, reencryptEuint8 } from "../reencrypt"; +import { reencryptEbool, reencryptEbytes64 } from "../reencrypt"; import { getSigners, initSigners } from "../signers"; import { bigIntToBytes64 } from "../utils"; import { deployEmployerClaimFixture } from "./fixture/EmployerClaim.fixture"; From 75503cbfce8a868f16dba2e445d72c0b416af6ec Mon Sep 17 00:00:00 2001 From: Aurora Poppyseed <30662672+poppyseedDev@users.noreply.github.com> Date: Fri, 13 Dec 2024 19:21:39 -0300 Subject: [PATCH 6/6] updated did --- hardhat/contracts/decIdentity/Diploma.sol | 7 ++----- hardhat/contracts/decIdentity/IdMapping.sol | 3 +-- hardhat/contracts/decIdentity/PassportID.sol | 12 +++--------- hardhat/test/decIdentity/diploma.ts | 2 +- 4 files changed, 7 insertions(+), 17 deletions(-) diff --git a/hardhat/contracts/decIdentity/Diploma.sol b/hardhat/contracts/decIdentity/Diploma.sol index a7fc29d..ff73b0c 100644 --- a/hardhat/contracts/decIdentity/Diploma.sol +++ b/hardhat/contracts/decIdentity/Diploma.sol @@ -30,7 +30,7 @@ contract Diploma is SepoliaZamaFHEVMConfig, AccessControl { /// @dev Structure to hold encrypted diploma data struct DiplomaData { - euint64 id; // Encrypted unique diploma ID + euint128 id; // Encrypted unique diploma ID ebytes64 university; // Encrypted university identifier euint16 degree; // Encrypted degree identifier ebytes64 grade; // Encrypted grade @@ -119,7 +119,7 @@ contract Diploma is SepoliaZamaFHEVMConfig, AccessControl { if (registered[userId]) revert DiplomaAlreadyRegistered(); // Generate a new encrypted diploma ID - euint64 newId = TFHE.randEuint64(); + euint128 newId = TFHE.randEuint128(); // Store the encrypted diploma data diplomaRecords[userId] = DiplomaData({ @@ -202,9 +202,6 @@ contract Diploma is SepoliaZamaFHEVMConfig, AccessControl { /// @dev Grant temporary access for graduate's data to be used in claim generation TFHE.allowTransient(diplomaRecords[userId].degree, claimAddress); - /// @dev Ensure the sender can access this graduate's data - if (!TFHE.isSenderAllowed(diplomaRecords[userId].degree)) revert AccessNotPermitted(); - /// @dev Attempt the external call and capture the result (bool success, bytes memory data) = claimAddress.call(abi.encodeWithSignature(claimFn, userId)); if (!success) revert ClaimGenerationFailed(data); diff --git a/hardhat/contracts/decIdentity/IdMapping.sol b/hardhat/contracts/decIdentity/IdMapping.sol index 4d28ea4..d3935ae 100644 --- a/hardhat/contracts/decIdentity/IdMapping.sol +++ b/hardhat/contracts/decIdentity/IdMapping.sol @@ -57,7 +57,6 @@ contract IdMapping is SepoliaZamaFHEVMConfig, Ownable2Step { */ function generateId() public returns (uint256) { if (addressToId[msg.sender] != 0) revert IdAlreadyGenerated(); - if (msg.sender == address(0)) revert InvalidAddress(); uint256 newId = nextId; @@ -92,7 +91,7 @@ contract IdMapping is SepoliaZamaFHEVMConfig, Ownable2Step { * @custom:throws NoAddressFound if no address is associated with the ID */ function getAddr(uint256 _id) public view returns (address) { - if (_id <= 0 || _id >= nextId) revert InvalidId(); + if (_id == 0 || _id >= nextId) revert InvalidId(); address addr = idToAddress[_id]; if (addr == address(0)) revert NoAddressFound(); return addr; diff --git a/hardhat/contracts/decIdentity/PassportID.sol b/hardhat/contracts/decIdentity/PassportID.sol index a717e85..fd2a37a 100644 --- a/hardhat/contracts/decIdentity/PassportID.sol +++ b/hardhat/contracts/decIdentity/PassportID.sol @@ -38,7 +38,7 @@ contract PassportID is SepoliaZamaFHEVMConfig, AccessControl { * @param birthdate Encrypted date of birth in unix timestamp format */ struct Identity { - euint64 id; /// @dev Encrypted unique ID + euint128 id; /// @dev Encrypted unique ID ebytes64 biodata; /// @dev Encrypted biodata (e.g., biometric data or hashed identity data) ebytes64 firstname; /// @dev Encrypted first name ebytes64 lastname; /// @dev Encrypted last name @@ -108,7 +108,7 @@ contract PassportID is SepoliaZamaFHEVMConfig, AccessControl { if (registered[userId]) revert AlreadyRegistered(); /// @dev Generate a new encrypted unique ID - euint64 newId = TFHE.randEuint64(); + euint128 newId = TFHE.randEuint128(); /// @dev Store the encrypted identity data citizenIdentities[userId] = Identity({ @@ -150,7 +150,7 @@ contract PassportID is SepoliaZamaFHEVMConfig, AccessControl { * @return Tuple containing (id, biodata, firstname, lastname, birthdate) * @custom:throws IdentityNotRegistered if no identity exists for userId */ - function getIdentity(uint256 userId) public view virtual returns (euint64, ebytes64, ebytes64, ebytes64, euint64) { + function getIdentity(uint256 userId) public view virtual returns (euint128, ebytes64, ebytes64, ebytes64, euint64) { if (!registered[userId]) revert IdentityNotRegistered(); return ( citizenIdentities[userId].id, @@ -200,9 +200,6 @@ contract PassportID is SepoliaZamaFHEVMConfig, AccessControl { /// @dev Grant temporary access for citizen's birthdate to be used in claim generation TFHE.allowTransient(citizenIdentities[userId].birthdate, claimAddress); - /// @dev Ensure the sender can access this citizen's birthdate - if (!TFHE.isSenderAllowed(citizenIdentities[userId].birthdate)) revert AccessNotPermitted(); - /// @dev Attempt the external call and capture the result (bool success, bytes memory data) = claimAddress.call(abi.encodeWithSignature(claimFn, userId)); if (!success) revert ClaimGenerationFailed(data); @@ -226,11 +223,8 @@ contract PassportID is SepoliaZamaFHEVMConfig, AccessControl { if (keccak256(bytes(fields[i])) == keccak256(bytes("id"))) { TFHE.allowTransient(citizenIdentities[userId].id, claimAddress); - /// @dev Ensure the sender can access this citizen's university - if (!TFHE.isSenderAllowed(citizenIdentities[userId].id)) revert AccessNotPermitted(); } else if (keccak256(bytes(fields[i])) == keccak256(bytes("birthdate"))) { TFHE.allowTransient(citizenIdentities[userId].birthdate, claimAddress); - if (!TFHE.isSenderAllowed(citizenIdentities[userId].birthdate)) revert AccessNotPermitted(); } else { revert InvalidField(); } diff --git a/hardhat/test/decIdentity/diploma.ts b/hardhat/test/decIdentity/diploma.ts index ec087d8..2228c10 100644 --- a/hardhat/test/decIdentity/diploma.ts +++ b/hardhat/test/decIdentity/diploma.ts @@ -5,7 +5,7 @@ import type { FhevmInstance } from "fhevmjs"; import type { Diploma, EmployerClaim, IdMapping, PassportID } from "../../types"; import { createInstance } from "../instance"; -import { reencryptEbool, reencryptEbytes64, reencryptEuint8, reencryptEuint16 } from "../reencrypt"; +import { reencryptEbool, reencryptEbytes64 } from "../reencrypt"; import { getSigners, initSigners } from "../signers"; import { bigIntToBytes64 } from "../utils"; import { deployEmployerClaimFixture } from "./fixture/EmployerClaim.fixture";