From 5f053574579063eda81387bff5e6f69eccbc7bd1 Mon Sep 17 00:00:00 2001 From: bamboo_chen Date: Thu, 17 Apr 2025 22:41:43 +0800 Subject: [PATCH 1/5] Register for OpenGuild Lost Tribes Challenges --- challenge-1-vesting/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/challenge-1-vesting/README.md b/challenge-1-vesting/README.md index 9cc7a2c..6f555f1 100644 --- a/challenge-1-vesting/README.md +++ b/challenge-1-vesting/README.md @@ -10,7 +10,7 @@ Add your information to the below list to officially participate in the workshop | Emoji | Name | Github Username | Occupations | | ----- | ---- | ------------------------------------- | ----------- | -| 🎅 | Ippo | [NTP-996](https://github.com/NTP-996) | DevRel | +| 🎅 | Chuhsin Chen | [bamboochen92518](https://github.com/bamboochen92518) | Student | ## 💻 Local development environment setup From 096e1cba121783af708ab9ed1a05973f7b4add10 Mon Sep 17 00:00:00 2001 From: bamboo_chen Date: Fri, 18 Apr 2025 13:57:19 +0800 Subject: [PATCH 2/5] finish challenge-1-vesting --- .../contracts/TokenVesting.sol | 86 +++++++++++++++++-- 1 file changed, 78 insertions(+), 8 deletions(-) diff --git a/challenge-1-vesting/contracts/TokenVesting.sol b/challenge-1-vesting/contracts/TokenVesting.sol index 43d4c3a..e1a45d9 100644 --- a/challenge-1-vesting/contracts/TokenVesting.sol +++ b/challenge-1-vesting/contracts/TokenVesting.sol @@ -29,19 +29,27 @@ import "@openzeppelin/contracts/utils/Pausable.sol"; import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; contract TokenVesting is Ownable(msg.sender), Pausable, ReentrancyGuard { - struct VestingSchedule { + // TODO: Define the vesting schedule struct + + struct VestingSchedule { + uint256 totalAmount; + uint256 startTime; + uint256 cliffDuration; + uint256 vestingDuration; + uint256 amountClaimed; + bool revoked; } - // Token being vested // TODO: Add state variables - + // Token being vested + IERC20 public token; // Mapping from beneficiary to vesting schedule - // TODO: Add state variables + mapping(address => VestingSchedule) public vestingSchedules; // Whitelist of beneficiaries - // TODO: Add state variables + mapping(address => bool) public whitelist; // Events event VestingScheduleCreated(address indexed beneficiary, uint256 amount); @@ -50,9 +58,10 @@ contract TokenVesting is Ownable(msg.sender), Pausable, ReentrancyGuard { event BeneficiaryWhitelisted(address indexed beneficiary); event BeneficiaryRemovedFromWhitelist(address indexed beneficiary); + // TODO: Initialize the contract constructor(address tokenAddress) { - // TODO: Initialize the contract - + require(tokenAddress != address(0), "Invalid token address"); + token = IERC20(tokenAddress); } // Modifier to check if beneficiary is whitelisted @@ -80,20 +89,81 @@ contract TokenVesting is Ownable(msg.sender), Pausable, ReentrancyGuard { uint256 startTime ) external onlyOwner onlyWhitelisted(beneficiary) whenNotPaused { // TODO: Implement vesting schedule creation + require(beneficiary != address(0), "Invalid beneficiary"); + require(amount > 0, "Amount must be greater than 0"); + require(vestingDuration > 0, "Vesting duration must be greater than 0"); + require(cliffDuration <= vestingDuration, "Cliff longer than vesting"); + require(vestingSchedules[beneficiary].totalAmount == 0, "Vesting schedule already exists"); + require(token.balanceOf(msg.sender) >= amount, "Insufficient token balance"); + require(token.allowance(msg.sender, address(this)) >= amount, "Insufficient token allowance"); + + vestingSchedules[beneficiary] = VestingSchedule({ + totalAmount: amount, + startTime: startTime == 0 ? block.timestamp : startTime, + cliffDuration: cliffDuration, + vestingDuration: vestingDuration, + amountClaimed: 0, + revoked: false + }); + + require(token.transferFrom(msg.sender, address(this), amount), "Token transfer failed"); + emit VestingScheduleCreated(beneficiary, amount); } function calculateVestedAmount( address beneficiary ) public view returns (uint256) { // TODO: Implement vested amount calculation + VestingSchedule memory schedule = vestingSchedules[beneficiary]; + + if (schedule.totalAmount == 0 || schedule.revoked) { + return 0; + } + + if (block.timestamp < schedule.startTime + schedule.cliffDuration) { + return 0; + } + + if (block.timestamp >= schedule.startTime + schedule.vestingDuration) { + return schedule.totalAmount - schedule.amountClaimed; + } + + uint256 timeElapsed = block.timestamp - schedule.startTime; + uint256 vestedAmount = (schedule.totalAmount * timeElapsed) / schedule.vestingDuration; + return vestedAmount - schedule.amountClaimed; } function claimVestedTokens() external nonReentrant whenNotPaused { - // TODO: Implement token claiming + // TODO: Implement token claiming + address beneficiary = msg.sender; + uint256 claimableAmount = calculateVestedAmount(beneficiary); + + require(claimableAmount > 0, "No tokens to claim"); + + VestingSchedule storage schedule = vestingSchedules[beneficiary]; + schedule.amountClaimed += claimableAmount; + + require(token.transfer(beneficiary, claimableAmount), "Token transfer failed"); + emit TokensClaimed(beneficiary, claimableAmount); } function revokeVesting(address beneficiary) external onlyOwner { // TODO: Implement vesting revocation + VestingSchedule storage schedule = vestingSchedules[beneficiary]; + require(schedule.totalAmount > 0, "No vesting schedule exists"); + require(!schedule.revoked, "Vesting already revoked"); + + uint256 unvestedAmount = schedule.totalAmount - schedule.amountClaimed; + uint256 claimableAmount = calculateVestedAmount(beneficiary); + + unvestedAmount -= claimableAmount; + schedule.revoked = true; + + if (unvestedAmount > 0) { + require(token.transfer(owner(), unvestedAmount), "Token transfer failed"); + } + + emit VestingRevoked(beneficiary); } From 5c65589744041032546358269338bdfa9f8931a1 Mon Sep 17 00:00:00 2001 From: bamboo_chen Date: Fri, 18 Apr 2025 14:13:45 +0800 Subject: [PATCH 3/5] finish challenge-2-yield-farm --- challenge-2-yield-farm/contracts/yeild.sol | 110 +++++++++++++++++++++ challenge-2-yield-farm/package-lock.json | 15 ++- challenge-2-yield-farm/package.json | 3 +- 3 files changed, 126 insertions(+), 2 deletions(-) diff --git a/challenge-2-yield-farm/contracts/yeild.sol b/challenge-2-yield-farm/contracts/yeild.sol index 421496a..17cca1e 100644 --- a/challenge-2-yield-farm/contracts/yeild.sol +++ b/challenge-2-yield-farm/contracts/yeild.sol @@ -71,6 +71,14 @@ contract YieldFarm is ReentrancyGuard, Ownable { uint256 _rewardRate ) Ownable(msg.sender) { // TODO: Initialize contract state + require(_lpToken != address(0), "Invalid LP token address"); + require(_rewardToken != address(0), "Invalid reward token address"); + require(_rewardRate > 0, "Reward rate must be greater than 0"); + + lpToken = IERC20(_lpToken); + rewardToken = IERC20(_rewardToken); + rewardRate = _rewardRate; + lastUpdateTime = block.timestamp; } function updateReward(address _user) internal { @@ -90,6 +98,12 @@ contract YieldFarm is ReentrancyGuard, Ownable { // 1. Calculate rewards since last update // 2. Apply boost multiplier // 3. Return total pending rewards + if (totalStaked == 0) { + return rewardPerTokenStored; + } + + uint256 timeElapsed = block.timestamp - lastUpdateTime; + return rewardPerTokenStored + ((timeElapsed * rewardRate * 1e18) / totalStaked); } function earned(address _user) public view returns (uint256) { @@ -98,6 +112,15 @@ contract YieldFarm is ReentrancyGuard, Ownable { // 1. Calculate rewards since last update // 2. Apply boost multiplier // 3. Return total pending rewards + UserInfo memory user = userInfo[_user]; + if (user.amount == 0) { + return user.pendingRewards; + } + + uint256 rewardPerTokenValue = rewardPerToken(); + uint256 boostedReward = ((user.amount * (rewardPerTokenValue - user.rewardDebt)) / 1e18); + uint256 boostMultiplier = calculateBoostMultiplier(_user); + return user.pendingRewards + ((boostedReward * boostMultiplier) / 100); } /** @@ -111,6 +134,30 @@ contract YieldFarm is ReentrancyGuard, Ownable { // 2. Transfer LP tokens from user // 3. Update user info and total staked amount // 4. Emit Staked event + require(_amount > 0, "Cannot stake 0"); + require( + lpToken.balanceOf(msg.sender) >= _amount, + "Insufficient LP token balance" + ); + require( + lpToken.allowance(msg.sender, address(this)) >= _amount, + "Insufficient LP token allowance" + ); + + updateReward(msg.sender); + + UserInfo storage user = userInfo[msg.sender]; + if (user.amount == 0) { + user.startTime = block.timestamp; + } + user.amount += _amount; + totalStaked += _amount; + + require( + lpToken.transferFrom(msg.sender, address(this), _amount), + "LP token transfer failed" + ); + emit Staked(msg.sender, _amount); } /** @@ -124,6 +171,20 @@ contract YieldFarm is ReentrancyGuard, Ownable { // 2. Transfer LP tokens to user // 3. Update user info and total staked amount // 4. Emit Withdrawn event + require(_amount > 0, "Amount must be greater than 0"); + UserInfo storage user = userInfo[msg.sender]; + require(user.amount >= _amount, "Insufficient balance"); + + updateReward(msg.sender); + + user.amount -= _amount; + totalStaked -= _amount; + + require( + lpToken.transfer(msg.sender, _amount), + "LP token transfer failed" + ); + emit Withdrawn(msg.sender, _amount); } /** @@ -136,6 +197,22 @@ contract YieldFarm is ReentrancyGuard, Ownable { // 2. Transfer rewards to user // 3. Update user reward debt // 4. Emit RewardsClaimed event + updateReward(msg.sender); + + UserInfo storage user = userInfo[msg.sender]; + uint256 rewards = user.pendingRewards; + require(rewards > 0, "No rewards to claim"); + require( + rewardToken.balanceOf(address(this)) >= rewards, + "Insufficient reward token balance" + ); + + user.pendingRewards = 0; + require( + rewardToken.transfer(msg.sender, rewards), + "Reward token transfer failed" + ); + emit RewardsClaimed(msg.sender, rewards); } /** @@ -147,6 +224,21 @@ contract YieldFarm is ReentrancyGuard, Ownable { // 1. Transfer all LP tokens back to user // 2. Reset user info // 3. Emit EmergencyWithdrawn event + UserInfo storage user = userInfo[msg.sender]; + uint256 amount = user.amount; + require(amount > 0, "No staked amount to withdraw"); + + totalStaked -= amount; + user.amount = 0; + user.pendingRewards = 0; + user.rewardDebt = 0; + user.startTime = 0; + + require( + lpToken.transfer(msg.sender, amount), + "LP token transfer failed" + ); + emit EmergencyWithdrawn(msg.sender, amount); } /** @@ -161,6 +253,21 @@ contract YieldFarm is ReentrancyGuard, Ownable { // Requirements: // 1. Calculate staking duration // 2. Return appropriate multiplier based on duration thresholds + UserInfo memory user = userInfo[_user]; + if (user.amount == 0 || user.startTime == 0) { + return 100; // 1x multiplier + } + + uint256 stakingDuration = block.timestamp - user.startTime; + if (stakingDuration >= BOOST_THRESHOLD_3) { + return 200; // 2x multiplier for 90+ days + } else if (stakingDuration >= BOOST_THRESHOLD_2) { + return 150; // 1.5x multiplier for 30+ days + } else if (stakingDuration >= BOOST_THRESHOLD_1) { + return 125; // 1.25x multiplier for 7+ days + } + return 100; // 1x multiplier for less than 7 days + } /** @@ -172,6 +279,9 @@ contract YieldFarm is ReentrancyGuard, Ownable { // Requirements: // 1. Update rewards before changing rate // 2. Set new reward rate + require(_newRate > 0, "Reward rate must be greater than 0"); + updateReward(address(0)); // Update global rewards before changing rate + rewardRate = _newRate; } /** diff --git a/challenge-2-yield-farm/package-lock.json b/challenge-2-yield-farm/package-lock.json index 4cbdfb0..d60931b 100644 --- a/challenge-2-yield-farm/package-lock.json +++ b/challenge-2-yield-farm/package-lock.json @@ -9,7 +9,8 @@ "version": "1.0.0", "license": "ISC", "dependencies": { - "@openzeppelin/contracts": "^5.1.0" + "@openzeppelin/contracts": "^5.1.0", + "dotenv": "^16.5.0" }, "devDependencies": { "@nomicfoundation/hardhat-toolbox": "^5.0.0", @@ -3383,6 +3384,18 @@ "node": ">=8" } }, + "node_modules/dotenv": { + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.5.0.tgz", + "integrity": "sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, "node_modules/dunder-proto": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.0.tgz", diff --git a/challenge-2-yield-farm/package.json b/challenge-2-yield-farm/package.json index 5366ac8..1d307cb 100644 --- a/challenge-2-yield-farm/package.json +++ b/challenge-2-yield-farm/package.json @@ -17,6 +17,7 @@ "hardhat": "^2.22.17" }, "dependencies": { - "@openzeppelin/contracts": "^5.1.0" + "@openzeppelin/contracts": "^5.1.0", + "dotenv": "^16.5.0" } } From f97be4d7ed0b954a03188b8bd71abf06a91cb7c7 Mon Sep 17 00:00:00 2001 From: bamboo_chen Date: Fri, 25 Apr 2025 17:04:59 +0800 Subject: [PATCH 4/5] update: optimize contract --- .../contracts/TokenVesting.sol | 214 +- challenge-1-vesting/hardhat.config.ts | 14 +- challenge-1-vesting/package-lock.json | 3314 ++++++++++++++++- challenge-1-vesting/package.json | 5 +- challenge-2-yield-farm/contracts/yeild.sol | 339 +- challenge-2-yield-farm/hardhat.config.ts | 11 +- challenge-2-yield-farm/package-lock.json | 45 +- challenge-2-yield-farm/package.json | 3 +- challenge-3-frontend/app/page.tsx | 82 +- challenge-3-frontend/app/vesting/loading.tsx | 17 + challenge-3-frontend/app/vesting/page.tsx | 18 + .../app/yield-farm/loading.tsx | 17 + challenge-3-frontend/app/yield-farm/page.tsx | 18 + 13 files changed, 3505 insertions(+), 592 deletions(-) create mode 100644 challenge-3-frontend/app/vesting/loading.tsx create mode 100644 challenge-3-frontend/app/vesting/page.tsx create mode 100644 challenge-3-frontend/app/yield-farm/loading.tsx create mode 100644 challenge-3-frontend/app/yield-farm/page.tsx diff --git a/challenge-1-vesting/contracts/TokenVesting.sol b/challenge-1-vesting/contracts/TokenVesting.sol index e1a45d9..c1e4bc4 100644 --- a/challenge-1-vesting/contracts/TokenVesting.sol +++ b/challenge-1-vesting/contracts/TokenVesting.sol @@ -1,218 +1,118 @@ -// Challenge: Token Vesting Contract -/* -Create a token vesting contract with the following requirements: - -1. The contract should allow an admin to create vesting schedules for different beneficiaries -2. Each vesting schedule should have: - - Total amount of tokens to be vested - - Cliff period (time before any tokens can be claimed) - - Vesting duration (total time for all tokens to vest) - - Start time -3. After the cliff period, tokens should vest linearly over time -4. Beneficiaries should be able to claim their vested tokens at any time -5. Admin should be able to revoke unvested tokens from a beneficiary - -Bonus challenges: -- Add support for multiple token types -- Implement a whitelist for beneficiaries -- Add emergency pause functionality - -Here's your starter code: -*/ - // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; -import "@openzeppelin/contracts/utils/Pausable.sol"; -import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; -contract TokenVesting is Ownable(msg.sender), Pausable, ReentrancyGuard { - - // TODO: Define the vesting schedule struct +contract TokenVesting is Ownable { + error EnforcedPause(); struct VestingSchedule { - uint256 totalAmount; - uint256 startTime; - uint256 cliffDuration; - uint256 vestingDuration; - uint256 amountClaimed; + uint128 totalAmount; + uint64 startTime; + uint32 cliffDuration; + uint32 vestingDuration; + uint128 amountClaimed; bool revoked; } - // TODO: Add state variables - // Token being vested - IERC20 public token; - - // Mapping from beneficiary to vesting schedule + IERC20 public immutable token; mapping(address => VestingSchedule) public vestingSchedules; - - // Whitelist of beneficiaries mapping(address => bool) public whitelist; + bool public paused; - // Events - event VestingScheduleCreated(address indexed beneficiary, uint256 amount); - event TokensClaimed(address indexed beneficiary, uint256 amount); + event VestingScheduleCreated(address indexed beneficiary, uint128 amount); + event TokensClaimed(address indexed beneficiary, uint128 amount); event VestingRevoked(address indexed beneficiary); - event BeneficiaryWhitelisted(address indexed beneficiary); - event BeneficiaryRemovedFromWhitelist(address indexed beneficiary); + event Whitelisted(address indexed beneficiary); + event Unwhitelisted(address indexed beneficiary); + event Paused(); + event Unpaused(); - // TODO: Initialize the contract - constructor(address tokenAddress) { - require(tokenAddress != address(0), "Invalid token address"); + constructor(address tokenAddress) Ownable(msg.sender) { + require(tokenAddress != address(0)); token = IERC20(tokenAddress); } - // Modifier to check if beneficiary is whitelisted modifier onlyWhitelisted(address beneficiary) { require(whitelist[beneficiary], "Beneficiary not whitelisted"); _; } + modifier whenNotPaused() { + if (paused) revert EnforcedPause(); + _; + } + function addToWhitelist(address beneficiary) external onlyOwner { - require(beneficiary != address(0), "Invalid address"); + require(beneficiary != address(0)); whitelist[beneficiary] = true; - emit BeneficiaryWhitelisted(beneficiary); + emit Whitelisted(beneficiary); } function removeFromWhitelist(address beneficiary) external onlyOwner { whitelist[beneficiary] = false; - emit BeneficiaryRemovedFromWhitelist(beneficiary); + emit Unwhitelisted(beneficiary); } function createVestingSchedule( address beneficiary, - uint256 amount, - uint256 cliffDuration, - uint256 vestingDuration, - uint256 startTime + uint128 amount, + uint32 cliffDuration, + uint32 vestingDuration, + uint64 startTime ) external onlyOwner onlyWhitelisted(beneficiary) whenNotPaused { - // TODO: Implement vesting schedule creation - require(beneficiary != address(0), "Invalid beneficiary"); - require(amount > 0, "Amount must be greater than 0"); - require(vestingDuration > 0, "Vesting duration must be greater than 0"); - require(cliffDuration <= vestingDuration, "Cliff longer than vesting"); - require(vestingSchedules[beneficiary].totalAmount == 0, "Vesting schedule already exists"); - require(token.balanceOf(msg.sender) >= amount, "Insufficient token balance"); - require(token.allowance(msg.sender, address(this)) >= amount, "Insufficient token allowance"); + require(beneficiary != address(0) && amount > 0 && vestingDuration > 0 && cliffDuration <= vestingDuration); + require(vestingSchedules[beneficiary].totalAmount == 0); + require(token.transferFrom(msg.sender, address(this), amount)); vestingSchedules[beneficiary] = VestingSchedule({ totalAmount: amount, - startTime: startTime == 0 ? block.timestamp : startTime, + startTime: startTime == 0 ? uint64(block.timestamp) : startTime, cliffDuration: cliffDuration, vestingDuration: vestingDuration, amountClaimed: 0, revoked: false }); - require(token.transferFrom(msg.sender, address(this), amount), "Token transfer failed"); emit VestingScheduleCreated(beneficiary, amount); } - function calculateVestedAmount( - address beneficiary - ) public view returns (uint256) { - // TODO: Implement vested amount calculation - VestingSchedule memory schedule = vestingSchedules[beneficiary]; - - if (schedule.totalAmount == 0 || schedule.revoked) { - return 0; - } - - if (block.timestamp < schedule.startTime + schedule.cliffDuration) { - return 0; - } - - if (block.timestamp >= schedule.startTime + schedule.vestingDuration) { - return schedule.totalAmount - schedule.amountClaimed; - } - - uint256 timeElapsed = block.timestamp - schedule.startTime; - uint256 vestedAmount = (schedule.totalAmount * timeElapsed) / schedule.vestingDuration; - return vestedAmount - schedule.amountClaimed; + function calculateVestedAmount(address beneficiary) public view returns (uint256) { + VestingSchedule memory s = vestingSchedules[beneficiary]; + if (s.totalAmount == 0 || s.revoked || block.timestamp < s.startTime + s.cliffDuration) return 0; + if (block.timestamp >= s.startTime + s.vestingDuration) return s.totalAmount - s.amountClaimed; + return ((s.totalAmount * (block.timestamp - s.startTime)) / s.vestingDuration) - s.amountClaimed; } - function claimVestedTokens() external nonReentrant whenNotPaused { - // TODO: Implement token claiming - address beneficiary = msg.sender; - uint256 claimableAmount = calculateVestedAmount(beneficiary); - - require(claimableAmount > 0, "No tokens to claim"); - - VestingSchedule storage schedule = vestingSchedules[beneficiary]; - schedule.amountClaimed += claimableAmount; + function claimVestedTokens() external whenNotPaused { + uint256 claimable = calculateVestedAmount(msg.sender); + require(claimable > 0, "No tokens to claim"); - require(token.transfer(beneficiary, claimableAmount), "Token transfer failed"); - emit TokensClaimed(beneficiary, claimableAmount); + vestingSchedules[msg.sender].amountClaimed += uint128(claimable); + require(token.transfer(msg.sender, claimable)); + emit TokensClaimed(msg.sender, uint128(claimable)); } function revokeVesting(address beneficiary) external onlyOwner { - // TODO: Implement vesting revocation - VestingSchedule storage schedule = vestingSchedules[beneficiary]; - require(schedule.totalAmount > 0, "No vesting schedule exists"); - require(!schedule.revoked, "Vesting already revoked"); - - uint256 unvestedAmount = schedule.totalAmount - schedule.amountClaimed; - uint256 claimableAmount = calculateVestedAmount(beneficiary); - - unvestedAmount -= claimableAmount; - schedule.revoked = true; - - if (unvestedAmount > 0) { - require(token.transfer(owner(), unvestedAmount), "Token transfer failed"); - } - - emit VestingRevoked(beneficiary); + VestingSchedule storage s = vestingSchedules[beneficiary]; + require(s.totalAmount > 0 && !s.revoked); + uint256 claimable = calculateVestedAmount(beneficiary); + uint256 unvested = s.totalAmount - s.amountClaimed - claimable; + s.revoked = true; + + if (unvested > 0) require(token.transfer(owner(), unvested)); + emit VestingRevoked(beneficiary); } function pause() external onlyOwner { - _pause(); + paused = true; + emit Paused(); } function unpause() external onlyOwner { - _unpause(); + paused = false; + emit Unpaused(); } -} - -/* -Solution template (key points to implement): - -1. VestingSchedule struct should contain: - - Total amount - - Start time - - Cliff duration - - Vesting duration - - Amount claimed - - Revoked status - -2. State variables needed: - - Mapping of beneficiary address to VestingSchedule - - ERC20 token reference - - Owner/admin address - -3. createVestingSchedule should: - - Validate input parameters - - Create new vesting schedule - - Transfer tokens to contract - - Emit event - -4. calculateVestedAmount should: - - Check if cliff period has passed - - Calculate linear vesting based on time passed - - Account for already claimed tokens - - Handle revoked status - -5. claimVestedTokens should: - - Calculate claimable amount - - Update claimed amount - - Transfer tokens - - Emit event - -6. revokeVesting should: - - Only allow admin - - Calculate and transfer unvested tokens back - - Mark schedule as revoked - - Emit event -*/ \ No newline at end of file +} \ No newline at end of file diff --git a/challenge-1-vesting/hardhat.config.ts b/challenge-1-vesting/hardhat.config.ts index 24ee97a..1e63ccb 100644 --- a/challenge-1-vesting/hardhat.config.ts +++ b/challenge-1-vesting/hardhat.config.ts @@ -2,6 +2,7 @@ import { HardhatUserConfig } from "hardhat/config"; import "@nomicfoundation/hardhat-toolbox"; import "@nomicfoundation/hardhat-ignition"; import "dotenv/config"; +import "hardhat-contract-sizer"; const config: HardhatUserConfig = { solidity: { @@ -11,8 +12,8 @@ const config: HardhatUserConfig = { enabled: true, runs: 1, // Lower optimization runs for simpler bytecode }, - evmVersion: "london", // Use an older EVM version for better compatibility - viaIR: false, // Disable IR-based compilation + evmVersion: "london", // Try istanbul for better compatibility + viaIR: true, }, }, networks: { @@ -20,10 +21,17 @@ const config: HardhatUserConfig = { url: "https://westend-asset-hub-eth-rpc.polkadot.io", chainId: 420420421, accounts: process.env.PRIVATE_KEY ? [process.env.PRIVATE_KEY] : [], - gasPrice: "auto", + gasPrice: "auto", // Dynamic pricing to avoid gas issues + gas: 15000000, // High gas limit for deployment timeout: 100000, }, }, + contractSizer: { + alphaSort: true, + disambiguatePaths: false, + runOnCompile: true, + unit: "B", + }, }; export default config; diff --git a/challenge-1-vesting/package-lock.json b/challenge-1-vesting/package-lock.json index ebb18e8..3029312 100644 --- a/challenge-1-vesting/package-lock.json +++ b/challenge-1-vesting/package-lock.json @@ -15,7 +15,10 @@ }, "devDependencies": { "@nomicfoundation/hardhat-toolbox": "^5.0.0", - "hardhat": "^2.22.17" + "@nomiclabs/hardhat-web3": "^2.0.1", + "hardhat": "^2.22.17", + "hardhat-contract-sizer": "^2.10.0", + "web3": "^1.10.4" } }, "node_modules/@adraffy/ens-normalize": { @@ -23,6 +26,17 @@ "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==" }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.1.90" + } + }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", @@ -36,12 +50,63 @@ "node": ">=12" } }, + "node_modules/@ethereumjs/common": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.6.5.tgz", + "integrity": "sha512-lRyVQOeCDaIVtgfbowla32pzeDv2Obr8oR8Put5RdUBNRGr1VGPGQNGP6elWIpgK3YdpzqTOh4GyUGOureVeeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "crc-32": "^1.2.0", + "ethereumjs-util": "^7.1.5" + } + }, + "node_modules/@ethereumjs/common/node_modules/ethereum-cryptography": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", + "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/pbkdf2": "^3.0.0", + "@types/secp256k1": "^4.0.1", + "blakejs": "^1.1.0", + "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.0", + "pbkdf2": "^3.0.17", + "randombytes": "^2.1.0", + "safe-buffer": "^5.1.2", + "scrypt-js": "^3.0.0", + "secp256k1": "^4.0.1", + "setimmediate": "^1.0.5" + } + }, + "node_modules/@ethereumjs/common/node_modules/ethereumjs-util": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz", + "integrity": "sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@types/bn.js": "^5.1.0", + "bn.js": "^5.1.2", + "create-hash": "^1.1.2", + "ethereum-cryptography": "^0.1.3", + "rlp": "^2.2.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/@ethereumjs/rlp": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/@ethereumjs/rlp/-/rlp-4.0.1.tgz", "integrity": "sha512-tqsQiBQDQdmPWE1xkkBq4rlSW5QZpLOUJ5RJh2/9fug+q9tnUhuZoVLk7s0scUIKTOzEtR72DFBXI4WiZcMpvw==", "dev": true, - "peer": true, "bin": { "rlp": "bin/rlp" }, @@ -49,12 +114,63 @@ "node": ">=14" } }, + "node_modules/@ethereumjs/tx": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@ethereumjs/tx/-/tx-3.5.2.tgz", + "integrity": "sha512-gQDNJWKrSDGu2w7w0PzVXVBNMzb7wwdDOmOqczmhNjqFxFuIbhVJDwiGEnxFNC2/b8ifcZzY7MLcluizohRzNw==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@ethereumjs/common": "^2.6.4", + "ethereumjs-util": "^7.1.5" + } + }, + "node_modules/@ethereumjs/tx/node_modules/ethereum-cryptography": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", + "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/pbkdf2": "^3.0.0", + "@types/secp256k1": "^4.0.1", + "blakejs": "^1.1.0", + "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.0", + "pbkdf2": "^3.0.17", + "randombytes": "^2.1.0", + "safe-buffer": "^5.1.2", + "scrypt-js": "^3.0.0", + "secp256k1": "^4.0.1", + "setimmediate": "^1.0.5" + } + }, + "node_modules/@ethereumjs/tx/node_modules/ethereumjs-util": { + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz", + "integrity": "sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "@types/bn.js": "^5.1.0", + "bn.js": "^5.1.2", + "create-hash": "^1.1.2", + "ethereum-cryptography": "^0.1.3", + "rlp": "^2.2.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/@ethereumjs/util": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/@ethereumjs/util/-/util-8.1.0.tgz", "integrity": "sha512-zQ0IqbdX8FZ9aw11vP+dZkKDkS+kgIvQPHnSAXzP9pLu+Rfu3D3XEeLbicvoXJTYnhZiPmsZUxgdzXwNKxRPbA==", "dev": true, - "peer": true, "dependencies": { "@ethereumjs/rlp": "^4.0.1", "ethereum-cryptography": "^2.0.0", @@ -69,7 +185,6 @@ "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", "dev": true, - "peer": true, "dependencies": { "@noble/hashes": "1.4.0" }, @@ -82,7 +197,6 @@ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", "dev": true, - "peer": true, "engines": { "node": ">= 16" }, @@ -95,7 +209,6 @@ "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.4.0.tgz", "integrity": "sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==", "dev": true, - "peer": true, "dependencies": { "@noble/curves": "~1.4.0", "@noble/hashes": "~1.4.0", @@ -110,7 +223,6 @@ "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.3.0.tgz", "integrity": "sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==", "dev": true, - "peer": true, "dependencies": { "@noble/hashes": "~1.4.0", "@scure/base": "~1.1.6" @@ -124,7 +236,6 @@ "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", "integrity": "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==", "dev": true, - "peer": true, "dependencies": { "@noble/curves": "1.4.2", "@noble/hashes": "1.4.0", @@ -1531,6 +1642,17 @@ "node": ">= 12" } }, + "node_modules/@nomiclabs/hardhat-web3": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@nomiclabs/hardhat-web3/-/hardhat-web3-2.0.1.tgz", + "integrity": "sha512-PfIiMUL5xWpkkt1Gvfb8qJ4DUtqU++rTh/B/80aONwTniSoT12YlXQukdZoHGlpD1IBEG9y4+0OULRnWz5ywLQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "hardhat": "^2.0.0", + "web3": "^1.0.0-beta.36" + } + }, "node_modules/@openzeppelin/contracts": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-5.1.0.tgz", @@ -1670,6 +1792,19 @@ "node": ">=6" } }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, "node_modules/@solidity-parser/parser": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/@solidity-parser/parser/-/parser-0.14.5.tgz", @@ -1680,6 +1815,19 @@ "antlr4ts": "^0.5.0-alpha.4" } }, + "node_modules/@szmarczak/http-timer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", + "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", + "dev": true, + "license": "MIT", + "dependencies": { + "defer-to-connect": "^2.0.1" + }, + "engines": { + "node": ">=14.16" + } + }, "node_modules/@tsconfig/node10": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", @@ -1787,6 +1935,19 @@ "@types/node": "*" } }, + "node_modules/@types/cacheable-request": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", + "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "^3.1.4", + "@types/node": "*", + "@types/responselike": "^1.0.0" + } + }, "node_modules/@types/chai": { "version": "4.3.20", "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.20.tgz", @@ -1835,6 +1996,23 @@ "@types/node": "*" } }, + "node_modules/@types/http-cache-semantics": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", + "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/keyv": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-5.1.1.tgz", @@ -1884,6 +2062,16 @@ "dev": true, "peer": true }, + "node_modules/@types/responselike": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", + "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/secp256k1": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.6.tgz", @@ -1899,6 +2087,27 @@ "dev": true, "peer": true }, + "node_modules/abortcontroller-polyfill": { + "version": "1.7.8", + "resolved": "https://registry.npmjs.org/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.8.tgz", + "integrity": "sha512-9f1iZ2uWh92VcrU9Y8x+LdM4DLj75VE0MJB8zuF1iUnroEptStw+DQ8EQPMUdfe5k+PkB1uUfDQfWbhstH8LrQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/acorn": { "version": "8.14.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", @@ -2092,6 +2301,13 @@ "node": ">=6" } }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "dev": true, + "license": "MIT" + }, "node_modules/array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", @@ -2119,6 +2335,26 @@ "dev": true, "peer": true }, + "node_modules/asn1": { + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", + "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, "node_modules/assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", @@ -2145,12 +2381,18 @@ "dev": true, "peer": true }, + "node_modules/async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "dev": true, + "license": "MIT" + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true, - "peer": true + "dev": true }, "node_modules/at-least-node": { "version": "1.0.0", @@ -2162,6 +2404,39 @@ "node": ">= 4.0.0" } }, + "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/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz", + "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==", + "dev": true, + "license": "MIT" + }, "node_modules/axios": { "version": "1.7.9", "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", @@ -2187,6 +2462,44 @@ "safe-buffer": "^5.0.1" } }, + "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" + } + ], + "license": "MIT" + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/bcrypt-pbkdf/node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "dev": true, + "license": "Unlicense" + }, "node_modules/bech32": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", @@ -2194,6 +2507,16 @@ "dev": true, "peer": true }, + "node_modules/bignumber.js": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.0.tgz", + "integrity": "sha512-EM7aMFTXbptt/wZdMlBv2t8IViwQL+h6SLHosp8Yf0dqJMTnY6iL32opnAB6kAdL0SZPuvcAzFr31o0c/R3/RA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", @@ -2210,11 +2533,76 @@ "resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.2.1.tgz", "integrity": "sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==" }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true, + "license": "MIT" + }, "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==" }, + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "dev": true, + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/body-parser/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/body-parser/node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "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/boxen": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/boxen/-/boxen-5.1.2.tgz", @@ -2307,22 +2695,123 @@ "safe-buffer": "^5.1.2" } }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" - }, - "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==" - }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", - "engines": { - "node": ">= 0.8" + "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/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/buffer-to-arraybuffer": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz", + "integrity": "sha512-3dthu5CYiVB1DEJp61FtApNnNndTckcqe4pFcLdvHtrpG+kcyekCJKg4MRiDcFW7A6AODnXB9U4dwQiCW5kzJQ==", + "dev": true, + "license": "MIT" + }, + "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==" + }, + "node_modules/bufferutil": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/bufferutil/-/bufferutil-4.0.9.tgz", + "integrity": "sha512-WDtdLmJvAuNNPzByAYpRo2rF1Mmradw6gvWsQKf63476DDXmomT9zUiGypLcG4ibIM67vhAj8jJRdbmEws2Aqw==", + "devOptional": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cacheable-lookup": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-6.1.0.tgz", + "integrity": "sha512-KJ/Dmo1lDDhmW2XDPMo+9oiy/CeqosPguPCrgcVzKyZrL6pM1gU2GmPY/xo6OQPTUaA/c0kwHuywB4E6nmT9ww==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.6.0" + } + }, + "node_modules/cacheable-request": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", + "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", + "dev": true, + "license": "MIT", + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cacheable-request/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cacheable-request/node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" } }, "node_modules/call-bind": { @@ -2330,7 +2819,6 @@ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", "dev": true, - "peer": true, "dependencies": { "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", @@ -2345,11 +2833,11 @@ } }, "node_modules/call-bind-apply-helpers": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", - "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", "dev": true, - "peer": true, + "license": "MIT", "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" @@ -2358,6 +2846,23 @@ "node": ">= 0.4" } }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/camelcase": { "version": "6.3.0", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", @@ -2373,8 +2878,7 @@ "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", - "dev": true, - "peer": true + "dev": true }, "node_modules/cbor": { "version": "8.1.0", @@ -2472,11 +2976,49 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true, + "license": "ISC" + }, "node_modules/ci-info": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" }, + "node_modules/cids": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/cids/-/cids-0.7.5.tgz", + "integrity": "sha512-zT7mPeghoWAu+ppn8+BS1tQ5qGmbMfB4AregnQjA/qHY3GC1m1ptI9GkWNlgeu38r7CuRdXB47uY2XgAYt6QVA==", + "deprecated": "This module has been superseded by the multiformats module", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "class-is": "^1.1.0", + "multibase": "~0.6.0", + "multicodec": "^1.0.0", + "multihashes": "~0.4.15" + }, + "engines": { + "node": ">=4.0.0", + "npm": ">=3.0.0" + } + }, + "node_modules/cids/node_modules/multicodec": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-1.0.4.tgz", + "integrity": "sha512-NDd7FeS3QamVtbgfvu5h7fd1IlbaC4EQ0/pgU4zqE2vdHCmBGsUa0TiM8/TdSeG6BMPC92OOCf8F1ocE/Wkrrg==", + "deprecated": "This module has been superseded by the multiformats module", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer": "^5.6.0", + "varint": "^5.0.0" + } + }, "node_modules/cipher-base": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.6.tgz", @@ -2489,6 +3031,13 @@ "node": ">= 0.10" } }, + "node_modules/class-is": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/class-is/-/class-is-1.1.0.tgz", + "integrity": "sha512-rhjH9AG1fvabIDoGRVH587413LPjTZgmDF9fOFCbFJQV4yuocX1mHxxvXI4g3cGwbVY9wAYIoKlg1N79frJKQw==", + "dev": true, + "license": "MIT" + }, "node_modules/clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", @@ -2582,6 +3131,19 @@ "wrap-ansi": "^7.0.0" } }, + "node_modules/clone-response": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-response": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -2613,7 +3175,6 @@ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "dev": true, - "peer": true, "dependencies": { "delayed-stream": "~1.0.0" }, @@ -2820,6 +3381,41 @@ "safe-buffer": "~5.1.0" } }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-hash": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/content-hash/-/content-hash-2.5.2.tgz", + "integrity": "sha512-FvIQKy0S1JaWV10sMsA7TRx8bpU+pqPkhbsfvOJAdjRXvYxEckAwQWGwtRjiaJfh+E0DvcWUGqcdjwMGFjsSdw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cids": "^0.7.1", + "multicodec": "^0.5.5", + "multihashes": "^0.4.15" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/cookie": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", @@ -2828,6 +3424,13 @@ "node": ">= 0.6" } }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "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", @@ -2835,6 +3438,33 @@ "dev": true, "peer": true }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/create-hash": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", @@ -2867,6 +3497,16 @@ "devOptional": true, "peer": true }, + "node_modules/cross-fetch": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-4.1.0.tgz", + "integrity": "sha512-uKm5PU+MHTootlWEY+mZ4vvXoCn4fLQxT9dSc1sXVMSFkINTJVN8cAQROpwcKm8bJ/c7rgZVIBWzH5T78sNZZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "node-fetch": "^2.7.0" + } + }, "node_modules/crypt": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", @@ -2877,6 +3517,33 @@ "node": "*" } }, + "node_modules/d": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz", + "integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==", + "dev": true, + "license": "ISC", + "dependencies": { + "es5-ext": "^0.10.64", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "dev": true, + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/death": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/death/-/death-1.1.0.tgz", @@ -2911,6 +3578,45 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/decode-uri-component": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz", + "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/deep-eql": { "version": "4.1.4", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.4.tgz", @@ -2941,12 +3647,21 @@ "dev": true, "peer": true }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "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, - "peer": true, "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -2964,7 +3679,6 @@ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", "dev": true, - "peer": true, "engines": { "node": ">=0.4.0" } @@ -2977,6 +3691,17 @@ "node": ">= 0.8" } }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, "node_modules/diff": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", @@ -3011,6 +3736,12 @@ "node": ">=8" } }, + "node_modules/dom-walk": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", + "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==", + "dev": true + }, "node_modules/dotenv": { "version": "16.4.7", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz", @@ -3023,13 +3754,13 @@ } }, "node_modules/dunder-proto": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.0.tgz", - "integrity": "sha512-9+Sj30DIu+4KvHqMfLUGLFYL2PkURSYMVXJyXe92nFRvlYq5hBjLEhblKB+vkd/WVlUYMWigiY07T91Fkk0+4A==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", "dev": true, - "peer": true, + "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.0", + "call-bind-apply-helpers": "^1.0.1", "es-errors": "^1.3.0", "gopd": "^1.2.0" }, @@ -3037,6 +3768,24 @@ "node": ">= 0.4" } }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true, + "license": "MIT" + }, "node_modules/elliptic": { "version": "6.5.4", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", @@ -3061,6 +3810,26 @@ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, "node_modules/enquirer": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", @@ -3086,7 +3855,6 @@ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", "dev": true, - "peer": true, "engines": { "node": ">= 0.4" } @@ -3096,23 +3864,92 @@ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", "dev": true, - "peer": true, "engines": { "node": ">= 0.4" } }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, "engines": { - "node": ">=6" + "node": ">= 0.4" } }, - "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==", + "node_modules/es5-ext": { + "version": "0.10.64", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", + "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", + "dev": true, + "hasInstallScript": true, + "license": "ISC", + "dependencies": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "esniff": "^2.0.1", + "next-tick": "^1.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", + "dev": true, + "license": "MIT", + "dependencies": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/es6-symbol": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz", + "integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==", + "dev": true, + "license": "ISC", + "dependencies": { + "d": "^1.0.2", + "ext": "^1.7.0" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true, + "license": "MIT" + }, + "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==", "engines": { "node": ">=10" }, @@ -3157,6 +3994,22 @@ "node": ">=0.8.0" } }, + "node_modules/esniff": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", + "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", + "dev": true, + "license": "ISC", + "dependencies": { + "d": "^1.0.1", + "es5-ext": "^0.10.62", + "event-emitter": "^0.3.5", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/esprima": { "version": "2.7.3", "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", @@ -3191,6 +4044,34 @@ "node": ">=0.10.0" } }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eth-ens-namehash": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz", + "integrity": "sha512-VWEI1+KJfz4Km//dadyvBBoBeSQ0MHTXPvr8UIXiLW6IanxvAV+DmlZAijZwAyggqGUfwQBeHf7tc9wzc1piSw==", + "dev": true, + "license": "ISC", + "dependencies": { + "idna-uts46-hx": "^2.3.1", + "js-sha3": "^0.5.7" + } + }, + "node_modules/eth-ens-namehash/node_modules/js-sha3": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.5.7.tgz", + "integrity": "sha512-GII20kjaPX0zJ8wzkTbNDYMY7msuZcTWk8S5UOh6806Jq/wz1J8/bnr8uGU0DAUmYDjj2Mr4X1cW8v/GLYnR+g==", + "dev": true, + "license": "MIT" + }, "node_modules/eth-gas-reporter": { "version": "0.2.27", "resolved": "https://registry.npmjs.org/eth-gas-reporter/-/eth-gas-reporter-0.2.27.tgz", @@ -3270,12 +4151,52 @@ "@ethersproject/wordlists": "5.7.0" } }, + "node_modules/eth-lib": { + "version": "0.1.29", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.1.29.tgz", + "integrity": "sha512-bfttrr3/7gG4E02HoWTDUcDDslN003OlOoBxk9virpAZQ1ja/jDgwkWB8QfJF7ojuEowrqy+lzp9VcJG7/k5bQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "nano-json-stream-parser": "^0.1.2", + "servify": "^0.1.12", + "ws": "^3.0.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/eth-lib/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/eth-lib/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/eth-lib/node_modules/ws": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-3.3.3.tgz", + "integrity": "sha512-nnWLa/NwZSt4KQJu51MYlCcSQ5g7INpOrOMt4XV8j4dqTXdmlUmSHQ8/oLC069ckre0fRsgfvsKwbTdtKLCDkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-limiter": "~1.0.0", + "safe-buffer": "~5.1.0", + "ultron": "~1.1.0" + } + }, "node_modules/ethereum-bloom-filters": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/ethereum-bloom-filters/-/ethereum-bloom-filters-1.2.0.tgz", "integrity": "sha512-28hyiE7HVsWubqhpVLVmZXFd4ITeHi+BUu05o9isf0GUpMtzBUi+8/gFrGaGYzvGAJQmJ3JKj77Mk9G98T84rA==", "dev": true, - "peer": true, "dependencies": { "@noble/hashes": "^1.4.0" } @@ -3285,7 +4206,6 @@ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.6.1.tgz", "integrity": "sha512-pq5D8h10hHBjyqX+cfBm0i8JUXJ0UhczFc4r74zbuT9XgewFo2E3J1cOaGtdZynILNmQ685YWGzGE1Zv6io50w==", "dev": true, - "peer": true, "engines": { "node": "^14.21.3 || >=16" }, @@ -3449,7 +4369,6 @@ "resolved": "https://registry.npmjs.org/ethjs-unit/-/ethjs-unit-0.1.6.tgz", "integrity": "sha512-/Sn9Y0oKl0uqQuvgFk/zQgR7aw1g36qX/jzSQ5lSwlO0GigPymk4eGQfeNTD03w1dPOqfz8V77Cy43jH56pagw==", "dev": true, - "peer": true, "dependencies": { "bn.js": "4.11.6", "number-to-bn": "1.7.0" @@ -3463,8 +4382,7 @@ "version": "4.11.6", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", "integrity": "sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA==", - "dev": true, - "peer": true + "dev": true }, "node_modules/ethjs-util": { "version": "0.1.6", @@ -3479,6 +4397,24 @@ "npm": ">=3" } }, + "node_modules/event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.4.tgz", + "integrity": "sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ==", + "dev": true, + "license": "MIT" + }, "node_modules/evp_bytestokey": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", @@ -3488,11 +4424,127 @@ "safe-buffer": "^5.1.1" } }, + "node_modules/express": { + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.12", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express/node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/express/node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "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/ext": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", + "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", + "dev": true, + "license": "ISC", + "dependencies": { + "type": "^2.7.2" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true, + "license": "MIT" + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "license": "MIT" + }, "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==", - "peer": true + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" }, "node_modules/fast-glob": { "version": "3.3.2", @@ -3511,6 +4563,13 @@ "node": ">=8.6.0" } }, + "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", @@ -3558,6 +4617,42 @@ "node": ">=8" } }, + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, "node_modules/find-replace": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", @@ -3613,6 +4708,32 @@ } } }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "*" + } + }, "node_modules/form-data": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", @@ -3628,11 +4749,38 @@ "node": ">= 6" } }, + "node_modules/form-data-encoder": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.1.tgz", + "integrity": "sha512-EFRDrsMm/kyqbTQocNvRXMLjc7Es2Vk+IQFx/YW7hkUH1eBl4J1fqiP34l74Yt0pFLCNpc06fkbVk00008mzjg==", + "dev": true, + "license": "MIT" + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/fp-ts": { "version": "1.19.3", "resolved": "https://registry.npmjs.org/fp-ts/-/fp-ts-1.19.3.tgz", "integrity": "sha512-H5KQDspykdHuztLTg+ajGN0Z2qUjcEf3Ybxc6hLt0k7/zPkn29XnKnxlBPyW2XIddWrGaJBzBl4VLYOtk39yZg==" }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/fs-extra": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", @@ -3646,6 +4794,16 @@ "node": ">=6 <7 || >=8" } }, + "node_modules/fs-minipass": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "dev": true, + "license": "ISC", + "dependencies": { + "minipass": "^2.6.0" + } + }, "node_modules/fs-readdir-recursive": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", @@ -3676,7 +4834,6 @@ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "dev": true, - "peer": true, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -3700,20 +4857,22 @@ } }, "node_modules/get-intrinsic": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.5.tgz", - "integrity": "sha512-Y4+pKa7XeRUPWFNvOOYHkRYrfzW07oraURSvjDmRVOJ748OrVmeXtpE4+GCEHncjCjkTxPNRt8kEbxDhsn6VTg==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "dev": true, - "peer": true, + "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.0", - "dunder-proto": "^1.0.0", + "call-bind-apply-helpers": "^1.0.2", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", "function-bind": "^1.1.2", + "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-symbols": "^1.1.0", - "hasown": "^2.0.2" + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -3732,6 +4891,43 @@ "node": ">=4" } }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "dev": true, + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0" + } + }, "node_modules/ghost-testrpc": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/ghost-testrpc/-/ghost-testrpc-0.0.2.tgz", @@ -3854,6 +5050,17 @@ "node": ">= 6" } }, + "node_modules/global": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", + "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "min-document": "^2.19.0", + "process": "^0.11.10" + } + }, "node_modules/global-modules": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", @@ -3953,7 +5160,6 @@ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "dev": true, - "peer": true, "engines": { "node": ">= 0.4" }, @@ -3961,6 +5167,34 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/got": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/got/-/got-12.1.0.tgz", + "integrity": "sha512-hBv2ty9QN2RdbJJMK3hesmSkFTjVIHyIDDbssCKnSmq62edGgImJWD10Eb1k77TiV1bxloxqcFAVK8+9pkhOig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^4.6.0", + "@szmarczak/http-timer": "^5.0.1", + "@types/cacheable-request": "^6.0.2", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^6.0.4", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "form-data-encoder": "1.7.1", + "get-stream": "^6.0.1", + "http2-wrapper": "^2.1.10", + "lowercase-keys": "^3.0.0", + "p-cancelable": "^3.0.0", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -3988,6 +5222,55 @@ "uglify-js": "^3.1.4" } }, + "node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "deprecated": "this library is no longer supported", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/har-validator/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/har-validator/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/hardhat": { "version": "2.22.17", "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.22.17.tgz", @@ -4054,6 +5337,37 @@ } } }, + "node_modules/hardhat-contract-sizer": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/hardhat-contract-sizer/-/hardhat-contract-sizer-2.10.0.tgz", + "integrity": "sha512-QiinUgBD5MqJZJh1hl1jc9dNnpJg7eE/w4/4GEnrcmZJJTDbVFNe3+/3Ep24XqISSkYxRz36czcPHKHd/a0dwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "cli-table3": "^0.6.0", + "strip-ansi": "^6.0.0" + }, + "peerDependencies": { + "hardhat": "^2.0.0" + } + }, + "node_modules/hardhat-contract-sizer/node_modules/cli-table3": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", + "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" + } + }, "node_modules/hardhat-gas-reporter": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/hardhat-gas-reporter/-/hardhat-gas-reporter-1.0.10.tgz", @@ -4082,7 +5396,6 @@ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, - "peer": true, "dependencies": { "es-define-property": "^1.0.0" }, @@ -4095,7 +5408,22 @@ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "dev": true, - "peer": true, + "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" }, @@ -4130,7 +5458,6 @@ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dev": true, - "peer": true, "dependencies": { "function-bind": "^1.1.2" }, @@ -4179,6 +5506,13 @@ "node": ">=6.0.0" } }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "dev": true, + "license": "BSD-2-Clause" + }, "node_modules/http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -4194,6 +5528,13 @@ "node": ">= 0.8" } }, + "node_modules/http-https": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/http-https/-/http-https-1.0.0.tgz", + "integrity": "sha512-o0PWwVCSp3O0wS6FvNr6xfBCHgt0m1tvPLFOCc2iFDKTRAXhB7m8klDf7ErowFH8POa6dVdGatKU5I1YYwzUyg==", + "dev": true, + "license": "ISC" + }, "node_modules/http-response-object": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/http-response-object/-/http-response-object-3.0.2.tgz", @@ -4211,6 +5552,36 @@ "dev": true, "peer": true }, + "node_modules/http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, + "node_modules/http2-wrapper": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz", + "integrity": "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.2.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, "node_modules/https-proxy-agent": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", @@ -4234,6 +5605,50 @@ "node": ">=0.10.0" } }, + "node_modules/idna-uts46-hx": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/idna-uts46-hx/-/idna-uts46-hx-2.3.1.tgz", + "integrity": "sha512-PWoF9Keq6laYdIRwwCdhTPl60xRqAloYNMQLiyUnG42VjT53oW07BXIRM+NK7eQjzXjAk2gUvX9caRxlnF9TAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "2.1.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/idna-uts46-hx/node_modules/punycode": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.0.tgz", + "integrity": "sha512-Yxz2kRwT90aPiWEMHVYnEf4+rhwF1tBmmZ4KepCP+Wkium9JxtWnUm1nqGwpiAHr/tnTSeHqr3wb++jgSkXjhA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "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" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -4306,6 +5721,33 @@ "fp-ts": "^1.0.0" } }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-arguments": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", + "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "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", @@ -4317,6 +5759,19 @@ "node": ">=8" } }, + "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-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -4333,6 +5788,32 @@ "node": ">=8" } }, + "node_modules/is-function": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz", + "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-generator-function": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", + "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-proto": "^1.0.0", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.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", @@ -4369,6 +5850,48 @@ "node": ">=8" } }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", + "dev": true, + "license": "MIT" + }, "node_modules/is-unicode-supported": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", @@ -4394,6 +5917,13 @@ "dev": true, "peer": true }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", + "dev": true, + "license": "MIT" + }, "node_modules/js-sha3": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", @@ -4410,6 +5940,27 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", + "dev": true, + "license": "MIT" + }, + "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": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true, + "license": "(AFL-2.1 OR BSD-3-Clause)" + }, "node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", @@ -4458,6 +6009,22 @@ "node": "*" } }, + "node_modules/jsprim": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz", + "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.4.0", + "verror": "1.10.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, "node_modules/keccak": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.4.tgz", @@ -4472,6 +6039,16 @@ "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, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, "node_modules/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", @@ -4574,6 +6151,19 @@ "get-func-name": "^2.0.1" } }, + "node_modules/lowercase-keys": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-3.0.0.tgz", + "integrity": "sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/lru_map": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.3.3.tgz", @@ -4593,6 +6183,16 @@ "dev": true, "peer": true }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -4603,6 +6203,16 @@ "safe-buffer": "^5.1.2" } }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/memorystream": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", @@ -4611,6 +6221,16 @@ "node": ">= 0.10.0" } }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -4621,12 +6241,21 @@ "node": ">= 8" } }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/micro-ftch": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/micro-ftch/-/micro-ftch-0.3.1.tgz", "integrity": "sha512-/0LLxhzP0tfiR5hcQebtudP56gUurs2CLkGarnCiB/OqEyUFQ6U3paQi/tgLv0hBJYt2rnr9MNpxz4fiiugstg==", - "dev": true, - "peer": true + "dev": true }, "node_modules/micromatch": { "version": "4.0.8", @@ -4655,12 +6284,24 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "dev": true, - "peer": true, "engines": { "node": ">= 0.6" } @@ -4670,7 +6311,6 @@ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, - "peer": true, "dependencies": { "mime-db": "1.52.0" }, @@ -4678,6 +6318,25 @@ "node": ">= 0.6" } }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/min-document": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", + "integrity": "sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ==", + "dev": true, + "dependencies": { + "dom-walk": "^0.1.0" + } + }, "node_modules/minimalistic-assert": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", @@ -4707,12 +6366,32 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "dev": true, + "license": "ISC", + "dependencies": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "node_modules/minizlib": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^2.9.0" + } + }, "node_modules/mkdirp": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", "dev": true, - "peer": true, "dependencies": { "minimist": "^1.2.6" }, @@ -4720,6 +6399,20 @@ "mkdirp": "bin/cmd.js" } }, + "node_modules/mkdirp-promise": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz", + "integrity": "sha512-Hepn5kb1lJPtVW84RFT40YG1OddBNTOVUZR2bzQUHc+Z03en8/3uX0+060JDhcEzyO08HmipsN9DcnFMxhIL9w==", + "deprecated": "This package is broken and no longer maintained. 'mkdirp' itself supports promises now, please switch to that.", + "dev": true, + "license": "ISC", + "dependencies": { + "mkdirp": "*" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/mnemonist": { "version": "0.38.5", "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.38.5.tgz", @@ -4821,21 +6514,82 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, + "node_modules/mock-fs": { + "version": "4.14.0", + "resolved": "https://registry.npmjs.org/mock-fs/-/mock-fs-4.14.0.tgz", + "integrity": "sha512-qYvlv/exQ4+svI3UOvPUpLDF0OMX5euvUH0Ny4N5QyRyhNdgAgUrVH3iUINSzEPLvx0kbo/Bp28GJKIqvE7URw==", + "dev": true, + "license": "MIT" + }, "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==" }, - "node_modules/ndjson": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ndjson/-/ndjson-2.0.0.tgz", - "integrity": "sha512-nGl7LRGrzugTtaFcJMhLbpzJM6XdivmbkdlaGcrk/LXg2KL/YBC6z1g70xh0/al+oFuVFP8N8kiWRucmeEH/qQ==", + "node_modules/multibase": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/multibase/-/multibase-0.6.1.tgz", + "integrity": "sha512-pFfAwyTjbbQgNc3G7D48JkJxWtoJoBMaR4xQUOuB8RnCgRqaYmWNFeJTTvrJ2w51bjLq2zTby6Rqj9TQ9elSUw==", + "deprecated": "This module has been superseded by the multiformats module", + "dev": true, + "license": "MIT", "dependencies": { - "json-stringify-safe": "^5.0.1", - "minimist": "^1.2.5", - "readable-stream": "^3.6.0", - "split2": "^3.0.0", - "through2": "^4.0.0" + "base-x": "^3.0.8", + "buffer": "^5.5.0" + } + }, + "node_modules/multicodec": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/multicodec/-/multicodec-0.5.7.tgz", + "integrity": "sha512-PscoRxm3f+88fAtELwUnZxGDkduE2HD9Q6GHUOywQLjOGT/HAdhjLDYNZ1e7VR0s0TP0EwZ16LNUTFpoBGivOA==", + "deprecated": "This module has been superseded by the multiformats module", + "dev": true, + "license": "MIT", + "dependencies": { + "varint": "^5.0.0" + } + }, + "node_modules/multihashes": { + "version": "0.4.21", + "resolved": "https://registry.npmjs.org/multihashes/-/multihashes-0.4.21.tgz", + "integrity": "sha512-uVSvmeCWf36pU2nB4/1kzYZjsXD9vofZKpgudqkceYY5g2aZZXJ5r9lxuzoRLl1OAp28XljXsEJ/X/85ZsKmKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "multibase": "^0.7.0", + "varint": "^5.0.0" + } + }, + "node_modules/multihashes/node_modules/multibase": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/multibase/-/multibase-0.7.0.tgz", + "integrity": "sha512-TW8q03O0f6PNFTQDvh3xxH03c8CjGaaYrjkl9UQPG6rz53TQzzxJVCIWVjzcbN/Q5Y53Zd0IBQBMVktVgNx4Fg==", + "deprecated": "This module has been superseded by the multiformats module", + "dev": true, + "license": "MIT", + "dependencies": { + "base-x": "^3.0.8", + "buffer": "^5.5.0" + } + }, + "node_modules/nano-json-stream-parser": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz", + "integrity": "sha512-9MqxMH/BSJC7dnLsEMPyfN5Dvoo49IsPFYMcHw3Bcfc2kN0lpHRBSzlMSVx4HGyJ7s9B31CyBTVehWJoQ8Ctew==", + "dev": true, + "license": "MIT" + }, + "node_modules/ndjson": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ndjson/-/ndjson-2.0.0.tgz", + "integrity": "sha512-nGl7LRGrzugTtaFcJMhLbpzJM6XdivmbkdlaGcrk/LXg2KL/YBC6z1g70xh0/al+oFuVFP8N8kiWRucmeEH/qQ==", + "dependencies": { + "json-stringify-safe": "^5.0.1", + "minimist": "^1.2.5", + "readable-stream": "^3.6.0", + "split2": "^3.0.0", + "through2": "^4.0.0" }, "bin": { "ndjson": "cli.js" @@ -4844,6 +6598,16 @@ "node": ">=10" } }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", @@ -4851,6 +6615,13 @@ "dev": true, "peer": true }, + "node_modules/next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", + "dev": true, + "license": "ISC" + }, "node_modules/node-addon-api": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.2.tgz", @@ -4866,6 +6637,27 @@ "lodash": "^4.17.21" } }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, "node_modules/node-gyp-build": { "version": "4.8.4", "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", @@ -4905,12 +6697,24 @@ "node": ">=0.10.0" } }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/number-to-bn": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/number-to-bn/-/number-to-bn-1.7.0.tgz", "integrity": "sha512-wsJ9gfSz1/s4ZsJN01lyonwuxA1tml6X1yBDnfpMglypcBRFZZkus26EdPSlqS5GJfYddVZa22p3VNb3z5m5Ig==", "dev": true, - "peer": true, "dependencies": { "bn.js": "4.11.6", "strip-hex-prefix": "1.0.0" @@ -4924,15 +6728,23 @@ "version": "4.11.6", "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.6.tgz", "integrity": "sha512-XWwnNNFCuuSQ0m3r3C4LE3EiORltHd9M05pq6FOlVeiophzRbMo50Sbz1ehl8K3Z+jw9+vmgnXefY1hz8X+2wA==", + "dev": true + }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", "dev": true, - "peer": true + "license": "Apache-2.0", + "engines": { + "node": "*" + } }, "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==", "dev": true, - "peer": true, "engines": { "node": ">=0.10.0" } @@ -4942,7 +6754,6 @@ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", "dev": true, - "peer": true, "engines": { "node": ">= 0.4" }, @@ -4955,6 +6766,29 @@ "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.4.tgz", "integrity": "sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==" }, + "node_modules/oboe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/oboe/-/oboe-2.1.5.tgz", + "integrity": "sha512-zRFWiF+FoicxEs3jNI/WYUrVEgA7DeET/InK0XQuudGHRg8iIob3cNPrJTKaz4004uaA9Pbe+Dwa8iluhjLZWA==", + "dev": true, + "license": "BSD", + "dependencies": { + "http-https": "^1.0.0" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -4996,6 +6830,16 @@ "node": ">=0.10.0" } }, + "node_modules/p-cancelable": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", + "integrity": "sha512-mlVgR3PGuzlo0MmTdk4cXqXWlwQDLnONTAg6sm62XkMJEiRxN3GL3SffkYvqwonbkJBcrI7Uvv5Zh9yjvn2iUw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.20" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -5045,6 +6889,23 @@ "dev": true, "peer": true }, + "node_modules/parse-headers": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/parse-headers/-/parse-headers-2.0.6.tgz", + "integrity": "sha512-Tz11t3uKztEW5FEVZnj1ox8GKblWn+PvHY9TmJV5Mll2uHEwRdR/5Li1OlXoECjLYkApdhWy44ocONwXLiKO5A==", + "dev": true, + "license": "MIT" + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -5068,6 +6929,13 @@ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, + "node_modules/path-to-regexp": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "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", @@ -5103,6 +6971,13 @@ "node": ">=0.12" } }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", + "dev": true, + "license": "MIT" + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -5129,6 +7004,16 @@ "node": ">=6" } }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/prelude-ls": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", @@ -5155,6 +7040,16 @@ "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", @@ -5184,6 +7079,20 @@ "node": ">= 6" } }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", @@ -5191,6 +7100,40 @@ "dev": true, "peer": true }, + "node_modules/psl": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz", + "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "funding": { + "url": "https://github.com/sponsors/lupomontero" + } + }, + "node_modules/pump": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", + "dev": true, + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.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/qs": { "version": "6.13.1", "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.1.tgz", @@ -5207,6 +7150,21 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/query-string": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", + "dev": true, + "license": "MIT", + "dependencies": { + "decode-uri-component": "^0.2.0", + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -5228,6 +7186,19 @@ ], "peer": true }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -5236,6 +7207,16 @@ "safe-buffer": "^5.1.0" } }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/raw-body": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", @@ -5361,6 +7342,75 @@ "node": ">=4" } }, + "node_modules/request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/request/node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/request/node_modules/qs": { + "version": "6.5.3", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz", + "integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/request/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "dev": true, + "license": "MIT", + "bin": { + "uuid": "bin/uuid" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -5389,6 +7439,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "dev": true, + "license": "MIT" + }, "node_modules/resolve-from": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", @@ -5399,6 +7456,29 @@ "node": ">=4" } }, + "node_modules/responselike": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "lowercase-keys": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/responselike/node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", @@ -5473,6 +7553,24 @@ } ] }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -5665,6 +7763,58 @@ "semver": "bin/semver.js" } }, + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/serialize-javascript": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", @@ -5673,12 +7823,44 @@ "randombytes": "^2.1.0" } }, + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/servify": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/servify/-/servify-0.1.12.tgz", + "integrity": "sha512-/xE6GvsKKqyo1BAY+KxOWXcLpPsUUyji7Qg3bVD7hh1eRze5bR1uYiuDA/k3Gof1s9BTzQZEJK8sNcNGFIzeWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "body-parser": "^1.16.0", + "cors": "^2.8.1", + "express": "^4.14.0", + "request": "^2.79.0", + "xhr": "^2.3.3" + }, + "engines": { + "node": ">=6" + } + }, "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, - "peer": true, "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", @@ -5796,7 +7978,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, - "peer": true, "dependencies": { "call-bind": "^1.0.7", "es-errors": "^1.3.0", @@ -5810,11 +7991,57 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" - }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "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/simple-get": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-2.8.2.tgz", + "integrity": "sha512-Ijd/rV5o+mSBBs4F/x9oDPtTx9Zb6X9brmnXvMW4J7IR15ngi9q5xxqWBKU744jTZiaXtxaPL7uHG6vtN8kUkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "decompress-response": "^3.3.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/simple-get/node_modules/decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-response": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==" + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", @@ -6049,6 +8276,39 @@ "dev": true, "peer": true }, + "node_modules/sshpk": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", + "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sshpk/node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", + "dev": true, + "license": "Unlicense" + }, "node_modules/stacktrace-parser": { "version": "0.1.10", "resolved": "https://registry.npmjs.org/stacktrace-parser/-/stacktrace-parser-0.1.10.tgz", @@ -6076,6 +8336,16 @@ "node": ">= 0.8" } }, + "node_modules/strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -6149,6 +8419,121 @@ "node": ">=8" } }, + "node_modules/swarm-js": { + "version": "0.1.42", + "resolved": "https://registry.npmjs.org/swarm-js/-/swarm-js-0.1.42.tgz", + "integrity": "sha512-BV7c/dVlA3R6ya1lMlSSNPLYrntt0LUq4YMgy3iwpCIc6rZnS5W2wUoctarZ5pXlpKtxDDf9hNziEkcfrxdhqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "bluebird": "^3.5.0", + "buffer": "^5.0.5", + "eth-lib": "^0.1.26", + "fs-extra": "^4.0.2", + "got": "^11.8.5", + "mime-types": "^2.1.16", + "mkdirp-promise": "^5.0.1", + "mock-fs": "^4.1.0", + "setimmediate": "^1.0.5", + "tar": "^4.0.2", + "xhr-request": "^1.0.1" + } + }, + "node_modules/swarm-js/node_modules/@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "dev": true, + "license": "MIT", + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/swarm-js/node_modules/cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.6.0" + } + }, + "node_modules/swarm-js/node_modules/fs-extra": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.3.tgz", + "integrity": "sha512-q6rbdDd1o2mAnQreO7YADIxf/Whx4AHBiRf6d+/cVT8h44ss+lHgxf1FemcqDnQt9X3ct4McHr+JMGlYSsK7Cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "node_modules/swarm-js/node_modules/got": { + "version": "11.8.6", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", + "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=10.19.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/swarm-js/node_modules/http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/swarm-js/node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/swarm-js/node_modules/p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/sync-request": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/sync-request/-/sync-request-6.1.0.tgz", @@ -6226,6 +8611,25 @@ "node": ">=8" } }, + "node_modules/tar": { + "version": "4.4.19", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.19.tgz", + "integrity": "sha512-a20gEsvHnWe0ygBY8JbxoM4w3SJdhc7ZAuxkLqh+nvNQN2IOt0B5lLgM490X5Hl8FF0dl0tOf2ewFYAlIFgzVA==", + "dev": true, + "license": "ISC", + "dependencies": { + "chownr": "^1.1.4", + "fs-minipass": "^1.2.7", + "minipass": "^2.9.0", + "minizlib": "^1.3.3", + "mkdirp": "^0.5.5", + "safe-buffer": "^5.2.1", + "yallist": "^3.1.1" + }, + "engines": { + "node": ">=4.5" + } + }, "node_modules/then-request": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/then-request/-/then-request-6.0.2.tgz", @@ -6280,6 +8684,16 @@ "readable-stream": "3" } }, + "node_modules/timed-out": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-4.0.1.tgz", + "integrity": "sha512-G7r3AhovYtr5YKOWQkta8RKAPb+J9IsO4uVmzjl8AZwfhs8UcUwTiD6gcJYSgOtzyjvQKrKYn41syHbUWMkafA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/tinyglobby": { "version": "0.2.10", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.10.tgz", @@ -6322,6 +8736,27 @@ "node": ">=0.6" } }, + "node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "dev": true, + "license": "MIT" + }, "node_modules/ts-command-line-args": { "version": "2.5.1", "resolved": "https://registry.npmjs.org/ts-command-line-args/-/ts-command-line-args-2.5.1.tgz", @@ -6412,6 +8847,19 @@ "resolved": "https://registry.npmjs.org/tsort/-/tsort-0.0.1.tgz", "integrity": "sha512-Tyrf5mxF8Ofs1tNoxA13lFeZ2Zrbd6cKbuH3V+MQ5sb6DtBj5FjrXVsRWT8YvNAQTqNoz66dz1WsbigI22aEnw==" }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, "node_modules/tweetnacl": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", @@ -6422,6 +8870,13 @@ "resolved": "https://registry.npmjs.org/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz", "integrity": "sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==" }, + "node_modules/type": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.3.tgz", + "integrity": "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==", + "dev": true, + "license": "ISC" + }, "node_modules/type-check": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", @@ -6456,6 +8911,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/typechain": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/typechain/-/typechain-8.3.2.tgz", @@ -6547,6 +9016,16 @@ "dev": true, "peer": true }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, "node_modules/typescript": { "version": "5.7.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", @@ -6585,6 +9064,13 @@ "node": ">=0.8.0" } }, + "node_modules/ultron": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ultron/-/ultron-1.1.1.tgz", + "integrity": "sha512-UIEXBNeYmKptWH6z8ZnqTeS8fV74zG0/eRU9VGkpzz+LIJNs8W/zM/L+7ctCkRrgbNnnR0xxw4bKOr0cW0N0Og==", + "dev": true, + "license": "MIT" + }, "node_modules/undici": { "version": "5.28.4", "resolved": "https://registry.npmjs.org/undici/-/undici-5.28.4.tgz", @@ -6617,18 +9103,72 @@ "node": ">= 0.8" } }, + "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/url-set-query": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-set-query/-/url-set-query-1.0.0.tgz", + "integrity": "sha512-3AChu4NiXquPfeckE5R5cGdiHCMWJx1dwCWOmWIL4KHAziJNOFIYJlpGFeKDvwLPHovZRCxK3cYlwzqI9Vp+Gg==", + "dev": true, + "license": "MIT" + }, + "node_modules/utf-8-validate": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz", + "integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==", + "devOptional": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-gyp-build": "^4.3.0" + }, + "engines": { + "node": ">=6.14.2" + } + }, "node_modules/utf8": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/utf8/-/utf8-3.0.0.tgz", "integrity": "sha512-E8VjFIQ/TyQgp+TZfS6l8yp/xWppSAHzidGiRrqe4bK4XP9pTRyKFgGJpO3SN7zdX4DeomTrwaseCHovfpFcqQ==", + "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==", "dev": true, - "peer": true + "license": "MIT", + "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==" }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", @@ -6644,12 +9184,443 @@ "devOptional": true, "peer": true }, + "node_modules/varint": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/varint/-/varint-5.0.2.tgz", + "integrity": "sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow==", + "dev": true, + "license": "MIT" + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "license": "MIT", + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/verror/node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/web3": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3/-/web3-1.10.4.tgz", + "integrity": "sha512-kgJvQZjkmjOEKimx/tJQsqWfRDPTTcBfYPa9XletxuHLpHcXdx67w8EFn5AW3eVxCutE9dTVHgGa9VYe8vgsEA==", + "dev": true, + "hasInstallScript": true, + "license": "LGPL-3.0", + "dependencies": { + "web3-bzz": "1.10.4", + "web3-core": "1.10.4", + "web3-eth": "1.10.4", + "web3-eth-personal": "1.10.4", + "web3-net": "1.10.4", + "web3-shh": "1.10.4", + "web3-utils": "1.10.4" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-bzz": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-bzz/-/web3-bzz-1.10.4.tgz", + "integrity": "sha512-ZZ/X4sJ0Uh2teU9lAGNS8EjveEppoHNQiKlOXAjedsrdWuaMErBPdLQjXfcrYvN6WM6Su9PMsAxf3FXXZ+HwQw==", + "dev": true, + "hasInstallScript": true, + "license": "LGPL-3.0", + "dependencies": { + "@types/node": "^12.12.6", + "got": "12.1.0", + "swarm-js": "^0.1.40" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-bzz/node_modules/@types/node": { + "version": "12.20.55", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", + "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/web3-core": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-core/-/web3-core-1.10.4.tgz", + "integrity": "sha512-B6elffYm81MYZDTrat7aEhnhdtVE3lDBUZft16Z8awYMZYJDbnykEbJVS+l3mnA7AQTnSDr/1MjWofGDLBJPww==", + "dev": true, + "license": "LGPL-3.0", + "dependencies": { + "@types/bn.js": "^5.1.1", + "@types/node": "^12.12.6", + "bignumber.js": "^9.0.0", + "web3-core-helpers": "1.10.4", + "web3-core-method": "1.10.4", + "web3-core-requestmanager": "1.10.4", + "web3-utils": "1.10.4" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-core-helpers": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-core-helpers/-/web3-core-helpers-1.10.4.tgz", + "integrity": "sha512-r+L5ylA17JlD1vwS8rjhWr0qg7zVoVMDvWhajWA5r5+USdh91jRUYosp19Kd1m2vE034v7Dfqe1xYRoH2zvG0g==", + "dev": true, + "license": "LGPL-3.0", + "dependencies": { + "web3-eth-iban": "1.10.4", + "web3-utils": "1.10.4" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-core-method": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-core-method/-/web3-core-method-1.10.4.tgz", + "integrity": "sha512-uZTb7flr+Xl6LaDsyTeE2L1TylokCJwTDrIVfIfnrGmnwLc6bmTWCCrm71sSrQ0hqs6vp/MKbQYIYqUN0J8WyA==", + "dev": true, + "license": "LGPL-3.0", + "dependencies": { + "@ethersproject/transactions": "^5.6.2", + "web3-core-helpers": "1.10.4", + "web3-core-promievent": "1.10.4", + "web3-core-subscriptions": "1.10.4", + "web3-utils": "1.10.4" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-core-promievent": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-core-promievent/-/web3-core-promievent-1.10.4.tgz", + "integrity": "sha512-2de5WnJQ72YcIhYwV/jHLc4/cWJnznuoGTJGD29ncFQHAfwW/MItHFSVKPPA5v8AhJe+r6y4Y12EKvZKjQVBvQ==", + "dev": true, + "license": "LGPL-3.0", + "dependencies": { + "eventemitter3": "4.0.4" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-core-requestmanager": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-core-requestmanager/-/web3-core-requestmanager-1.10.4.tgz", + "integrity": "sha512-vqP6pKH8RrhT/2MoaU+DY/OsYK9h7HmEBNCdoMj+4ZwujQtw/Mq2JifjwsJ7gits7Q+HWJwx8q6WmQoVZAWugg==", + "dev": true, + "license": "LGPL-3.0", + "dependencies": { + "util": "^0.12.5", + "web3-core-helpers": "1.10.4", + "web3-providers-http": "1.10.4", + "web3-providers-ipc": "1.10.4", + "web3-providers-ws": "1.10.4" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-core-subscriptions": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-core-subscriptions/-/web3-core-subscriptions-1.10.4.tgz", + "integrity": "sha512-o0lSQo/N/f7/L76C0HV63+S54loXiE9fUPfHFcTtpJRQNDBVsSDdWRdePbWwR206XlsBqD5VHApck1//jEafTw==", + "dev": true, + "license": "LGPL-3.0", + "dependencies": { + "eventemitter3": "4.0.4", + "web3-core-helpers": "1.10.4" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-core/node_modules/@types/node": { + "version": "12.20.55", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", + "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/web3-eth": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-eth/-/web3-eth-1.10.4.tgz", + "integrity": "sha512-Sql2kYKmgt+T/cgvg7b9ce24uLS7xbFrxE4kuuor1zSCGrjhTJ5rRNG8gTJUkAJGKJc7KgnWmgW+cOfMBPUDSA==", + "dev": true, + "license": "LGPL-3.0", + "dependencies": { + "web3-core": "1.10.4", + "web3-core-helpers": "1.10.4", + "web3-core-method": "1.10.4", + "web3-core-subscriptions": "1.10.4", + "web3-eth-abi": "1.10.4", + "web3-eth-accounts": "1.10.4", + "web3-eth-contract": "1.10.4", + "web3-eth-ens": "1.10.4", + "web3-eth-iban": "1.10.4", + "web3-eth-personal": "1.10.4", + "web3-net": "1.10.4", + "web3-utils": "1.10.4" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-eth-abi": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-eth-abi/-/web3-eth-abi-1.10.4.tgz", + "integrity": "sha512-cZ0q65eJIkd/jyOlQPDjr8X4fU6CRL1eWgdLwbWEpo++MPU/2P4PFk5ZLAdye9T5Sdp+MomePPJ/gHjLMj2VfQ==", + "dev": true, + "license": "LGPL-3.0", + "dependencies": { + "@ethersproject/abi": "^5.6.3", + "web3-utils": "1.10.4" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-eth-accounts": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-eth-accounts/-/web3-eth-accounts-1.10.4.tgz", + "integrity": "sha512-ysy5sVTg9snYS7tJjxVoQAH6DTOTkRGR8emEVCWNGLGiB9txj+qDvSeT0izjurS/g7D5xlMAgrEHLK1Vi6I3yg==", + "dev": true, + "license": "LGPL-3.0", + "dependencies": { + "@ethereumjs/common": "2.6.5", + "@ethereumjs/tx": "3.5.2", + "@ethereumjs/util": "^8.1.0", + "eth-lib": "0.2.8", + "scrypt-js": "^3.0.1", + "uuid": "^9.0.0", + "web3-core": "1.10.4", + "web3-core-helpers": "1.10.4", + "web3-core-method": "1.10.4", + "web3-utils": "1.10.4" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-eth-accounts/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/web3-eth-accounts/node_modules/eth-lib": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/eth-lib/-/eth-lib-0.2.8.tgz", + "integrity": "sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "bn.js": "^4.11.6", + "elliptic": "^6.4.0", + "xhr-request-promise": "^0.1.2" + } + }, + "node_modules/web3-eth-accounts/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/web3-eth-contract": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-eth-contract/-/web3-eth-contract-1.10.4.tgz", + "integrity": "sha512-Q8PfolOJ4eV9TvnTj1TGdZ4RarpSLmHnUnzVxZ/6/NiTfe4maJz99R0ISgwZkntLhLRtw0C7LRJuklzGYCNN3A==", + "dev": true, + "license": "LGPL-3.0", + "dependencies": { + "@types/bn.js": "^5.1.1", + "web3-core": "1.10.4", + "web3-core-helpers": "1.10.4", + "web3-core-method": "1.10.4", + "web3-core-promievent": "1.10.4", + "web3-core-subscriptions": "1.10.4", + "web3-eth-abi": "1.10.4", + "web3-utils": "1.10.4" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-eth-ens": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-eth-ens/-/web3-eth-ens-1.10.4.tgz", + "integrity": "sha512-LLrvxuFeVooRVZ9e5T6OWKVflHPFgrVjJ/jtisRWcmI7KN/b64+D/wJzXqgmp6CNsMQcE7rpmf4CQmJCrTdsgg==", + "dev": true, + "license": "LGPL-3.0", + "dependencies": { + "content-hash": "^2.5.2", + "eth-ens-namehash": "2.0.8", + "web3-core": "1.10.4", + "web3-core-helpers": "1.10.4", + "web3-core-promievent": "1.10.4", + "web3-eth-abi": "1.10.4", + "web3-eth-contract": "1.10.4", + "web3-utils": "1.10.4" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-eth-iban": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-eth-iban/-/web3-eth-iban-1.10.4.tgz", + "integrity": "sha512-0gE5iNmOkmtBmbKH2aTodeompnNE8jEyvwFJ6s/AF6jkw9ky9Op9cqfzS56AYAbrqEFuClsqB/AoRves7LDELw==", + "dev": true, + "license": "LGPL-3.0", + "dependencies": { + "bn.js": "^5.2.1", + "web3-utils": "1.10.4" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-eth-personal": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-eth-personal/-/web3-eth-personal-1.10.4.tgz", + "integrity": "sha512-BRa/hs6jU1hKHz+AC/YkM71RP3f0Yci1dPk4paOic53R4ZZG4MgwKRkJhgt3/GPuPliwS46f/i5A7fEGBT4F9w==", + "dev": true, + "license": "LGPL-3.0", + "dependencies": { + "@types/node": "^12.12.6", + "web3-core": "1.10.4", + "web3-core-helpers": "1.10.4", + "web3-core-method": "1.10.4", + "web3-net": "1.10.4", + "web3-utils": "1.10.4" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-eth-personal/node_modules/@types/node": { + "version": "12.20.55", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", + "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/web3-net": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-net/-/web3-net-1.10.4.tgz", + "integrity": "sha512-mKINnhOOnZ4koA+yV2OT5s5ztVjIx7IY9a03w6s+yao/BUn+Luuty0/keNemZxTr1E8Ehvtn28vbOtW7Ids+Ow==", + "dev": true, + "license": "LGPL-3.0", + "dependencies": { + "web3-core": "1.10.4", + "web3-core-method": "1.10.4", + "web3-utils": "1.10.4" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-providers-http": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-providers-http/-/web3-providers-http-1.10.4.tgz", + "integrity": "sha512-m2P5Idc8hdiO0l60O6DSCPw0kw64Zgi0pMjbEFRmxKIck2Py57RQMu4bxvkxJwkF06SlGaEQF8rFZBmuX7aagQ==", + "dev": true, + "license": "LGPL-3.0", + "dependencies": { + "abortcontroller-polyfill": "^1.7.5", + "cross-fetch": "^4.0.0", + "es6-promise": "^4.2.8", + "web3-core-helpers": "1.10.4" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-providers-ipc": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-providers-ipc/-/web3-providers-ipc-1.10.4.tgz", + "integrity": "sha512-YRF/bpQk9z3WwjT+A6FI/GmWRCASgd+gC0si7f9zbBWLXjwzYAKG73bQBaFRAHex1hl4CVcM5WUMaQXf3Opeuw==", + "dev": true, + "license": "LGPL-3.0", + "dependencies": { + "oboe": "2.1.5", + "web3-core-helpers": "1.10.4" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-providers-ws": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-providers-ws/-/web3-providers-ws-1.10.4.tgz", + "integrity": "sha512-j3FBMifyuFFmUIPVQR4pj+t5ILhAexAui0opgcpu9R5LxQrLRUZxHSnU+YO25UycSOa/NAX8A+qkqZNpcFAlxA==", + "dev": true, + "license": "LGPL-3.0", + "dependencies": { + "eventemitter3": "4.0.4", + "web3-core-helpers": "1.10.4", + "websocket": "^1.0.32" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/web3-shh": { + "version": "1.10.4", + "resolved": "https://registry.npmjs.org/web3-shh/-/web3-shh-1.10.4.tgz", + "integrity": "sha512-cOH6iFFM71lCNwSQrC3niqDXagMqrdfFW85hC9PFUrAr3PUrIem8TNstTc3xna2bwZeWG6OBy99xSIhBvyIACw==", + "dev": true, + "hasInstallScript": true, + "license": "LGPL-3.0", + "dependencies": { + "web3-core": "1.10.4", + "web3-core-method": "1.10.4", + "web3-core-subscriptions": "1.10.4", + "web3-net": "1.10.4" + }, + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/web3-utils": { "version": "1.10.4", "resolved": "https://registry.npmjs.org/web3-utils/-/web3-utils-1.10.4.tgz", "integrity": "sha512-tsu8FiKJLk2PzhDl9fXbGUWTkkVXYhtTA+SmEFkKft+9BgwLxfCRpU96sWv7ICC8zixBNd3JURVoiR3dUXgP8A==", "dev": true, - "peer": true, "dependencies": { "@ethereumjs/util": "^8.1.0", "bn.js": "^5.2.1", @@ -6669,7 +9640,6 @@ "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.4.2.tgz", "integrity": "sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==", "dev": true, - "peer": true, "dependencies": { "@noble/hashes": "1.4.0" }, @@ -6682,7 +9652,6 @@ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz", "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==", "dev": true, - "peer": true, "engines": { "node": ">= 16" }, @@ -6695,7 +9664,6 @@ "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.4.0.tgz", "integrity": "sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==", "dev": true, - "peer": true, "dependencies": { "@noble/curves": "~1.4.0", "@noble/hashes": "~1.4.0", @@ -6710,7 +9678,6 @@ "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.3.0.tgz", "integrity": "sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==", "dev": true, - "peer": true, "dependencies": { "@noble/hashes": "~1.4.0", "@scure/base": "~1.1.6" @@ -6724,7 +9691,6 @@ "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-2.2.1.tgz", "integrity": "sha512-r/W8lkHSiTLxUxW8Rf3u4HGB0xQweG2RyETjywylKZSzLWoWAijRz8WCuOtJ6wah+avllXBqZuk29HCCvhEIRg==", "dev": true, - "peer": true, "dependencies": { "@noble/curves": "1.4.2", "@noble/hashes": "1.4.0", @@ -6732,6 +9698,59 @@ "@scure/bip39": "1.3.0" } }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/websocket": { + "version": "1.0.35", + "resolved": "https://registry.npmjs.org/websocket/-/websocket-1.0.35.tgz", + "integrity": "sha512-/REy6amwPZl44DDzvRCkaI1q1bIiQB0mEFQLUrhz3z2EK91cp3n72rAjUlrTP0zV22HJIUOVHQGPxhFRjxjt+Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "bufferutil": "^4.0.1", + "debug": "^2.2.0", + "es5-ext": "^0.10.63", + "typedarray-to-buffer": "^3.1.5", + "utf-8-validate": "^5.0.2", + "yaeti": "^0.0.6" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/websocket/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/websocket/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -6745,6 +9764,28 @@ "which": "bin/which" } }, + "node_modules/which-typed-array": { + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/widest-line": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", @@ -6843,6 +9884,55 @@ } } }, + "node_modules/xhr": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/xhr/-/xhr-2.6.0.tgz", + "integrity": "sha512-/eCGLb5rxjx5e3mF1A7s+pLlR6CGyqWN91fv1JgER5mVWg1MZmlhBvy9kjcsOdRk8RrIujotWyJamfyrp+WIcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "global": "~4.4.0", + "is-function": "^1.0.1", + "parse-headers": "^2.0.0", + "xtend": "^4.0.0" + } + }, + "node_modules/xhr-request": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/xhr-request/-/xhr-request-1.1.0.tgz", + "integrity": "sha512-Y7qzEaR3FDtL3fP30k9wO/e+FBnBByZeybKOhASsGP30NIkRAAkKD/sCnLvgEfAIEC1rcmK7YG8f4oEnIrrWzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-to-arraybuffer": "^0.0.5", + "object-assign": "^4.1.1", + "query-string": "^5.0.1", + "simple-get": "^2.7.0", + "timed-out": "^4.0.1", + "url-set-query": "^1.0.0", + "xhr": "^2.0.4" + } + }, + "node_modules/xhr-request-promise": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/xhr-request-promise/-/xhr-request-promise-0.1.3.tgz", + "integrity": "sha512-YUBytBsuwgitWtdRzXDDkWAXzhdGB8bYm0sSzMPZT7Z2MBjMSTHFsyCT1yCRATY+XC69DUrQraRAEgcoCRaIPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "xhr-request": "^1.1.0" + } + }, + "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/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -6851,6 +9941,24 @@ "node": ">=10" } }, + "node_modules/yaeti": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/yaeti/-/yaeti-0.0.6.tgz", + "integrity": "sha512-MvQa//+KcZCUkBTIC9blM+CU9J2GzuTytsOUwf2lidtvkx/6gnEp1QvJv34t9vdjhFmha/mUiNDbN0D0mJWdug==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.32" + } + }, + "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/yargs": { "version": "16.2.0", "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", diff --git a/challenge-1-vesting/package.json b/challenge-1-vesting/package.json index e3d28da..51e2f13 100644 --- a/challenge-1-vesting/package.json +++ b/challenge-1-vesting/package.json @@ -11,7 +11,10 @@ "description": "", "devDependencies": { "@nomicfoundation/hardhat-toolbox": "^5.0.0", - "hardhat": "^2.22.17" + "@nomiclabs/hardhat-web3": "^2.0.1", + "hardhat": "^2.22.17", + "hardhat-contract-sizer": "^2.10.0", + "web3": "^1.10.4" }, "dependencies": { "@nomicfoundation/hardhat-ignition": "^0.15.8", diff --git a/challenge-2-yield-farm/contracts/yeild.sol b/challenge-2-yield-farm/contracts/yeild.sol index 17cca1e..0de0faf 100644 --- a/challenge-2-yield-farm/contracts/yeild.sol +++ b/challenge-2-yield-farm/contracts/yeild.sol @@ -1,295 +1,136 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; -import "@openzeppelin/contracts/access/Ownable.sol"; - -/** - * @title YieldFarm - * @notice Challenge: Implement a yield farming contract with the following requirements: - * - * 1. Users can stake LP tokens and earn reward tokens - * 2. Rewards are distributed based on time and amount staked - * 3. Implement reward boosting mechanism for long-term stakers - * 4. Add emergency withdrawal functionality - * 5. Implement reward rate adjustment mechanism - */ +interface IERC20 { + function transfer(address to, uint256 value) external returns (bool); + function transferFrom(address from, address to, uint256 value) external returns (bool); +} -contract YieldFarm is ReentrancyGuard, Ownable { - // LP token that users can stake +contract YieldFarm { IERC20 public lpToken; - - // Token given as reward IERC20 public rewardToken; - - // Reward rate per second uint256 public rewardRate; + uint64 public l; // lastUpdate + uint256 public rPTS; // rewardPerTokenStored + uint128 public totalStaked; + address public owner; - // Last update time - uint256 public lastUpdateTime; - - // Reward per token stored - uint256 public rewardPerTokenStored; - - // Total staked amount - uint256 public totalStaked; - - // User struct to track staking info struct UserInfo { - uint256 amount; // Amount of LP tokens staked - uint256 startTime; // Time when user started staking + uint128 amount; // LP tokens staked + uint64 startTime; // Staking start time uint256 rewardDebt; // Reward debt uint256 pendingRewards; // Unclaimed rewards } - // Mapping of user address to their info mapping(address => UserInfo) public userInfo; - // Boost multiplier thresholds (in seconds) - uint256 public constant BOOST_THRESHOLD_1 = 7 days; - uint256 public constant BOOST_THRESHOLD_2 = 30 days; - uint256 public constant BOOST_THRESHOLD_3 = 90 days; + uint32 public constant BOOST_1 = 7 days; + uint32 public constant BOOST_2 = 30 days; + uint32 public constant BOOST_3 = 90 days; - // Events event Staked(address indexed user, uint256 amount); event Withdrawn(address indexed user, uint256 amount); event RewardsClaimed(address indexed user, uint256 amount); event EmergencyWithdrawn(address indexed user, uint256 amount); - // TODO: Implement the following functions - - /** - * @notice Initialize the contract with the LP token and reward token addresses - * @param _lpToken Address of the LP token - * @param _rewardToken Address of the reward token - * @param _rewardRate Initial reward rate per second - */ - constructor( - address _lpToken, - address _rewardToken, - uint256 _rewardRate - ) Ownable(msg.sender) { - // TODO: Initialize contract state - require(_lpToken != address(0), "Invalid LP token address"); - require(_rewardToken != address(0), "Invalid reward token address"); - require(_rewardRate > 0, "Reward rate must be greater than 0"); + error OwnableUnauthorizedAccount(address account); - lpToken = IERC20(_lpToken); - rewardToken = IERC20(_rewardToken); - rewardRate = _rewardRate; - lastUpdateTime = block.timestamp; + modifier onlyOwner() { + if (owner != msg.sender) revert OwnableUnauthorizedAccount(msg.sender); + _; } - function updateReward(address _user) internal { - rewardPerTokenStored = rewardPerToken(); - lastUpdateTime = block.timestamp; - - if (_user != address(0)) { - UserInfo storage user = userInfo[_user]; - user.pendingRewards = earned(_user); - user.rewardDebt = (user.amount * rewardPerTokenStored) / 1e18; - } + constructor(address _lp, address _reward, uint256 _rate) { + owner = msg.sender; + lpToken = IERC20(_lp); + rewardToken = IERC20(_reward); + rewardRate = _rate; + l = uint64(block.timestamp); } function rewardPerToken() public view returns (uint256) { - // TODO: Implement pending rewards calculation - // Requirements: - // 1. Calculate rewards since last update - // 2. Apply boost multiplier - // 3. Return total pending rewards - if (totalStaked == 0) { - return rewardPerTokenStored; + if (totalStaked == 0) return rPTS; + unchecked { + return rPTS + ((block.timestamp - l) * rewardRate) / totalStaked; } - - uint256 timeElapsed = block.timestamp - lastUpdateTime; - return rewardPerTokenStored + ((timeElapsed * rewardRate * 1e18) / totalStaked); } - function earned(address _user) public view returns (uint256) { - // TODO: Implement pending rewards calculation - // Requirements: - // 1. Calculate rewards since last update - // 2. Apply boost multiplier - // 3. Return total pending rewards - UserInfo memory user = userInfo[_user]; - if (user.amount == 0) { - return user.pendingRewards; - } - - uint256 rewardPerTokenValue = rewardPerToken(); - uint256 boostedReward = ((user.amount * (rewardPerTokenValue - user.rewardDebt)) / 1e18); - uint256 boostMultiplier = calculateBoostMultiplier(_user); - return user.pendingRewards + ((boostedReward * boostMultiplier) / 100); + function calculateBoostMultiplier(address _user) public view returns (uint256) { + UserInfo memory u = userInfo[_user]; + if (u.amount == 0 || u.startTime == 0) return 100; + uint64 duration = uint64(block.timestamp) - u.startTime; + if (duration >= BOOST_3) return 200; + if (duration >= BOOST_2) return 150; + if (duration >= BOOST_1) return 125; + return 100; } - /** - * @notice Stake LP tokens into the farm - * @param _amount Amount of LP tokens to stake - */ - function stake(uint256 _amount) external nonReentrant { - // TODO: Implement staking logic - // Requirements: - // 1. Update rewards - // 2. Transfer LP tokens from user - // 3. Update user info and total staked amount - // 4. Emit Staked event - require(_amount > 0, "Cannot stake 0"); - require( - lpToken.balanceOf(msg.sender) >= _amount, - "Insufficient LP token balance" - ); - require( - lpToken.allowance(msg.sender, address(this)) >= _amount, - "Insufficient LP token allowance" - ); - - updateReward(msg.sender); - - UserInfo storage user = userInfo[msg.sender]; - if (user.amount == 0) { - user.startTime = block.timestamp; - } - user.amount += _amount; - totalStaked += _amount; - - require( - lpToken.transferFrom(msg.sender, address(this), _amount), - "LP token transfer failed" - ); - emit Staked(msg.sender, _amount); - } - - /** - * @notice Withdraw staked LP tokens - * @param _amount Amount of LP tokens to withdraw - */ - function withdraw(uint256 _amount) external nonReentrant { - // TODO: Implement withdrawal logic - // Requirements: - // 1. Update rewards - // 2. Transfer LP tokens to user - // 3. Update user info and total staked amount - // 4. Emit Withdrawn event - require(_amount > 0, "Amount must be greater than 0"); - UserInfo storage user = userInfo[msg.sender]; - require(user.amount >= _amount, "Insufficient balance"); - - updateReward(msg.sender); - - user.amount -= _amount; - totalStaked -= _amount; - - require( - lpToken.transfer(msg.sender, _amount), - "LP token transfer failed" - ); - emit Withdrawn(msg.sender, _amount); + function _up(address _user) private { + UserInfo storage u = userInfo[_user]; + uint256 rpt = rewardPerToken(); + u.pendingRewards = pendingRewards(_user); + u.rewardDebt = (u.amount * rpt); } - /** - * @notice Claim pending rewards - */ - function claimRewards() external nonReentrant { - // TODO: Implement reward claiming logic - // Requirements: - // 1. Calculate pending rewards with boost multiplier - // 2. Transfer rewards to user - // 3. Update user reward debt - // 4. Emit RewardsClaimed event - updateReward(msg.sender); - - UserInfo storage user = userInfo[msg.sender]; - uint256 rewards = user.pendingRewards; - require(rewards > 0, "No rewards to claim"); - require( - rewardToken.balanceOf(address(this)) >= rewards, - "Insufficient reward token balance" - ); - - user.pendingRewards = 0; - require( - rewardToken.transfer(msg.sender, rewards), - "Reward token transfer failed" - ); - emit RewardsClaimed(msg.sender, rewards); + function stake(uint256 _amt) external { + require(_amt > 0, "Cannot stake 0"); + _up(msg.sender); + UserInfo storage u = userInfo[msg.sender]; + if (u.amount == 0) u.startTime = uint64(block.timestamp); + u.amount += uint128(_amt); + totalStaked += uint128(_amt); + lpToken.transferFrom(msg.sender, address(this), _amt); + emit Staked(msg.sender, _amt); } - /** - * @notice Emergency withdraw without caring about rewards - */ - function emergencyWithdraw() external nonReentrant { - // TODO: Implement emergency withdrawal - // Requirements: - // 1. Transfer all LP tokens back to user - // 2. Reset user info - // 3. Emit EmergencyWithdrawn event - UserInfo storage user = userInfo[msg.sender]; - uint256 amount = user.amount; - require(amount > 0, "No staked amount to withdraw"); - - totalStaked -= amount; - user.amount = 0; - user.pendingRewards = 0; - user.rewardDebt = 0; - user.startTime = 0; - - require( - lpToken.transfer(msg.sender, amount), - "LP token transfer failed" - ); - emit EmergencyWithdrawn(msg.sender, amount); + function withdraw(uint256 _amt) external { + UserInfo storage u = userInfo[msg.sender]; + require(u.amount >= _amt, "Insufficient balance"); + _up(msg.sender); + u.amount -= uint128(_amt); + totalStaked -= uint128(_amt); + lpToken.transfer(msg.sender, _amt); + emit Withdrawn(msg.sender, _amt); } - /** - * @notice Calculate boost multiplier based on staking duration - * @param _user Address of the user - * @return Boost multiplier (100 = 1x, 150 = 1.5x, etc.) - */ - function calculateBoostMultiplier( - address _user - ) public view returns (uint256) { - // TODO: Implement boost multiplier calculation - // Requirements: - // 1. Calculate staking duration - // 2. Return appropriate multiplier based on duration thresholds - UserInfo memory user = userInfo[_user]; - if (user.amount == 0 || user.startTime == 0) { - return 100; // 1x multiplier + function claimRewards() external { + _up(msg.sender); + UserInfo storage u = userInfo[msg.sender]; + uint256 rewards = u.pendingRewards; + if (rewards > 0) { + u.pendingRewards = 0; + rewardToken.transfer(msg.sender, rewards); + emit RewardsClaimed(msg.sender, rewards); } + } - uint256 stakingDuration = block.timestamp - user.startTime; - if (stakingDuration >= BOOST_THRESHOLD_3) { - return 200; // 2x multiplier for 90+ days - } else if (stakingDuration >= BOOST_THRESHOLD_2) { - return 150; // 1.5x multiplier for 30+ days - } else if (stakingDuration >= BOOST_THRESHOLD_1) { - return 125; // 1.25x multiplier for 7+ days + function emergencyWithdraw() external { + UserInfo storage u = userInfo[msg.sender]; + uint256 amt = u.amount; + if (amt > 0) { + totalStaked -= uint128(amt); + u.amount = 0; + u.pendingRewards = 0; + u.rewardDebt = 0; + u.startTime = 0; + lpToken.transfer(msg.sender, amt); + emit EmergencyWithdrawn(msg.sender, amt); } - return 100; // 1x multiplier for less than 7 days - } - /** - * @notice Update reward rate - * @param _newRate New reward rate per second - */ - function updateRewardRate(uint256 _newRate) external onlyOwner { - // TODO: Implement reward rate update logic - // Requirements: - // 1. Update rewards before changing rate - // 2. Set new reward rate - require(_newRate > 0, "Reward rate must be greater than 0"); - updateReward(address(0)); // Update global rewards before changing rate - rewardRate = _newRate; + function updateRewardRate(uint256 _rate) external onlyOwner { + rPTS = rewardPerToken(); + l = uint64(block.timestamp); + rewardRate = _rate; } - /** - * @notice View function to see pending rewards for a user - * @param _user Address of the user - * @return Pending reward amount - */ - function pendingRewards(address _user) external view returns (uint256) { - return earned(_user); + function pendingRewards(address _user) public view returns (uint256) { + UserInfo memory u = userInfo[_user]; + if (u.amount == 0) return u.pendingRewards; + uint256 rpt = rewardPerToken(); + uint256 r = (u.amount * (rpt - u.rewardDebt)); + unchecked { + return u.pendingRewards + (r * calculateBoostMultiplier(_user)) / 100; + } } -} +} \ No newline at end of file diff --git a/challenge-2-yield-farm/hardhat.config.ts b/challenge-2-yield-farm/hardhat.config.ts index 24ee97a..f9c1864 100644 --- a/challenge-2-yield-farm/hardhat.config.ts +++ b/challenge-2-yield-farm/hardhat.config.ts @@ -2,6 +2,7 @@ import { HardhatUserConfig } from "hardhat/config"; import "@nomicfoundation/hardhat-toolbox"; import "@nomicfoundation/hardhat-ignition"; import "dotenv/config"; +import "hardhat-contract-sizer"; const config: HardhatUserConfig = { solidity: { @@ -11,8 +12,8 @@ const config: HardhatUserConfig = { enabled: true, runs: 1, // Lower optimization runs for simpler bytecode }, - evmVersion: "london", // Use an older EVM version for better compatibility - viaIR: false, // Disable IR-based compilation + evmVersion: "london", // Try istanbul for better compatibility + viaIR: true, }, }, networks: { @@ -24,6 +25,12 @@ const config: HardhatUserConfig = { timeout: 100000, }, }, + contractSizer: { + alphaSort: true, + disambiguatePaths: false, + runOnCompile: true, + unit: "B", + }, }; export default config; diff --git a/challenge-2-yield-farm/package-lock.json b/challenge-2-yield-farm/package-lock.json index d60931b..5f86ab9 100644 --- a/challenge-2-yield-farm/package-lock.json +++ b/challenge-2-yield-farm/package-lock.json @@ -14,7 +14,8 @@ }, "devDependencies": { "@nomicfoundation/hardhat-toolbox": "^5.0.0", - "hardhat": "^2.22.17" + "hardhat": "^2.22.17", + "hardhat-contract-sizer": "^2.10.0" } }, "node_modules/@adraffy/ens-normalize": { @@ -25,6 +26,17 @@ "license": "MIT", "peer": true }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.1.90" + } + }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", @@ -4548,6 +4560,37 @@ } } }, + "node_modules/hardhat-contract-sizer": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/hardhat-contract-sizer/-/hardhat-contract-sizer-2.10.0.tgz", + "integrity": "sha512-QiinUgBD5MqJZJh1hl1jc9dNnpJg7eE/w4/4GEnrcmZJJTDbVFNe3+/3Ep24XqISSkYxRz36czcPHKHd/a0dwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "cli-table3": "^0.6.0", + "strip-ansi": "^6.0.0" + }, + "peerDependencies": { + "hardhat": "^2.0.0" + } + }, + "node_modules/hardhat-contract-sizer/node_modules/cli-table3": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", + "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" + } + }, "node_modules/hardhat-gas-reporter": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/hardhat-gas-reporter/-/hardhat-gas-reporter-1.0.10.tgz", diff --git a/challenge-2-yield-farm/package.json b/challenge-2-yield-farm/package.json index 1d307cb..f323e01 100644 --- a/challenge-2-yield-farm/package.json +++ b/challenge-2-yield-farm/package.json @@ -14,7 +14,8 @@ }, "devDependencies": { "@nomicfoundation/hardhat-toolbox": "^5.0.0", - "hardhat": "^2.22.17" + "hardhat": "^2.22.17", + "hardhat-contract-sizer": "^2.10.0" }, "dependencies": { "@openzeppelin/contracts": "^5.1.0", diff --git a/challenge-3-frontend/app/page.tsx b/challenge-3-frontend/app/page.tsx index fb01185..68bb392 100644 --- a/challenge-3-frontend/app/page.tsx +++ b/challenge-3-frontend/app/page.tsx @@ -26,84 +26,16 @@ export default function Home() {
  • Mint/Redeem LST Bifrost
  • +
  • + Vesting +
  • +
  • + Yield farm +
  • -
    - - Vercel logomark - Deploy now - - - Read our docs - -
    ); diff --git a/challenge-3-frontend/app/vesting/loading.tsx b/challenge-3-frontend/app/vesting/loading.tsx new file mode 100644 index 0000000..6493637 --- /dev/null +++ b/challenge-3-frontend/app/vesting/loading.tsx @@ -0,0 +1,17 @@ +import { Skeleton } from "@/components/ui/skeleton" + +export default function Loading() { + // You can add any UI inside Loading, including a Skeleton. + return ( +
    + +
    + + + + +
    + +
    + ) +} \ No newline at end of file diff --git a/challenge-3-frontend/app/vesting/page.tsx b/challenge-3-frontend/app/vesting/page.tsx new file mode 100644 index 0000000..b77996d --- /dev/null +++ b/challenge-3-frontend/app/vesting/page.tsx @@ -0,0 +1,18 @@ +"use client"; +import SigpassKit from "@/components/sigpasskit"; +import Link from "next/link"; + +export default function WalletPage() { + return ( +
    +
    + Home + Wallet + Send transaction + Write contract +
    +

    Wallet

    + +
    + ); +} \ No newline at end of file diff --git a/challenge-3-frontend/app/yield-farm/loading.tsx b/challenge-3-frontend/app/yield-farm/loading.tsx new file mode 100644 index 0000000..6493637 --- /dev/null +++ b/challenge-3-frontend/app/yield-farm/loading.tsx @@ -0,0 +1,17 @@ +import { Skeleton } from "@/components/ui/skeleton" + +export default function Loading() { + // You can add any UI inside Loading, including a Skeleton. + return ( +
    + +
    + + + + +
    + +
    + ) +} \ No newline at end of file diff --git a/challenge-3-frontend/app/yield-farm/page.tsx b/challenge-3-frontend/app/yield-farm/page.tsx new file mode 100644 index 0000000..b77996d --- /dev/null +++ b/challenge-3-frontend/app/yield-farm/page.tsx @@ -0,0 +1,18 @@ +"use client"; +import SigpassKit from "@/components/sigpasskit"; +import Link from "next/link"; + +export default function WalletPage() { + return ( +
    +
    + Home + Wallet + Send transaction + Write contract +
    +

    Wallet

    + +
    + ); +} \ No newline at end of file From 3dbe161e108f3ffd9dd726fd495951e4d881c8d0 Mon Sep 17 00:00:00 2001 From: bamboo_chen Date: Sat, 26 Apr 2025 16:36:05 +0800 Subject: [PATCH 5/5] finish: UI --- challenge-3-frontend/app/providers.tsx | 2 +- .../app/tokenMint/loading.tsx | 17 + challenge-3-frontend/app/tokenMint/page.tsx | 16 + .../app/transferWND/loading.tsx | 17 + challenge-3-frontend/app/transferWND/page.tsx | 16 + challenge-3-frontend/app/vesting/page.tsx | 14 +- challenge-3-frontend/app/yield-farm/page.tsx | 14 +- challenge-3-frontend/components/erc20.tsx | 596 ++++++++ challenge-3-frontend/components/navbar.tsx | 18 +- .../components/transfer-wnd.tsx | 352 +++++ challenge-3-frontend/components/vesting.tsx | 959 ++++++++++++ .../components/write-contract.tsx | 4 +- challenge-3-frontend/components/yield.tsx | 1296 +++++++++++++++++ 13 files changed, 3297 insertions(+), 24 deletions(-) create mode 100644 challenge-3-frontend/app/tokenMint/loading.tsx create mode 100644 challenge-3-frontend/app/tokenMint/page.tsx create mode 100644 challenge-3-frontend/app/transferWND/loading.tsx create mode 100644 challenge-3-frontend/app/transferWND/page.tsx create mode 100644 challenge-3-frontend/components/erc20.tsx create mode 100644 challenge-3-frontend/components/transfer-wnd.tsx create mode 100644 challenge-3-frontend/components/vesting.tsx create mode 100644 challenge-3-frontend/components/yield.tsx diff --git a/challenge-3-frontend/app/providers.tsx b/challenge-3-frontend/app/providers.tsx index 91243fe..c929c05 100644 --- a/challenge-3-frontend/app/providers.tsx +++ b/challenge-3-frontend/app/providers.tsx @@ -66,7 +66,7 @@ export const localConfig = createConfig({ const { wallets } = getDefaultWallets(); // initialize and destructure wallets object -const config = getDefaultConfig({ +export const config = getDefaultConfig({ appName: "DOTUI", // Name your app projectId: "ddf8cf3ee0013535c3760d4c79c9c8b9", // Enter your WalletConnect Project ID here wallets: [ diff --git a/challenge-3-frontend/app/tokenMint/loading.tsx b/challenge-3-frontend/app/tokenMint/loading.tsx new file mode 100644 index 0000000..6493637 --- /dev/null +++ b/challenge-3-frontend/app/tokenMint/loading.tsx @@ -0,0 +1,17 @@ +import { Skeleton } from "@/components/ui/skeleton" + +export default function Loading() { + // You can add any UI inside Loading, including a Skeleton. + return ( +
    + +
    + + + + +
    + +
    + ) +} \ No newline at end of file diff --git a/challenge-3-frontend/app/tokenMint/page.tsx b/challenge-3-frontend/app/tokenMint/page.tsx new file mode 100644 index 0000000..7078c8a --- /dev/null +++ b/challenge-3-frontend/app/tokenMint/page.tsx @@ -0,0 +1,16 @@ +"use client"; +import MockERC20Interaction from "@/components/erc20"; +import SigpassKit from "@/components/sigpasskit"; +import Navbar from "@/components/navbar"; + +export default function WalletPage() { + return ( +
    + + +

    Mint / Transfer ERC20 Token

    + +
    + + ); +} \ No newline at end of file diff --git a/challenge-3-frontend/app/transferWND/loading.tsx b/challenge-3-frontend/app/transferWND/loading.tsx new file mode 100644 index 0000000..6493637 --- /dev/null +++ b/challenge-3-frontend/app/transferWND/loading.tsx @@ -0,0 +1,17 @@ +import { Skeleton } from "@/components/ui/skeleton" + +export default function Loading() { + // You can add any UI inside Loading, including a Skeleton. + return ( +
    + +
    + + + + +
    + +
    + ) +} \ No newline at end of file diff --git a/challenge-3-frontend/app/transferWND/page.tsx b/challenge-3-frontend/app/transferWND/page.tsx new file mode 100644 index 0000000..208810c --- /dev/null +++ b/challenge-3-frontend/app/transferWND/page.tsx @@ -0,0 +1,16 @@ +"use client"; +import TransferNativeToken from "@/components/transfer-wnd"; +import SigpassKit from "@/components/sigpasskit"; +import Navbar from "@/components/navbar"; + +export default function WalletPage() { + return ( +
    + + +

    Transfer WND

    + +
    + + ); +} \ No newline at end of file diff --git a/challenge-3-frontend/app/vesting/page.tsx b/challenge-3-frontend/app/vesting/page.tsx index b77996d..e84ca81 100644 --- a/challenge-3-frontend/app/vesting/page.tsx +++ b/challenge-3-frontend/app/vesting/page.tsx @@ -1,18 +1,16 @@ "use client"; +import TokenVesting from "@/components/vesting"; import SigpassKit from "@/components/sigpasskit"; -import Link from "next/link"; +import Navbar from "@/components/navbar"; export default function WalletPage() { return (
    -
    - Home - Wallet - Send transaction - Write contract -
    -

    Wallet

    + +

    Vesting

    +
    + ); } \ No newline at end of file diff --git a/challenge-3-frontend/app/yield-farm/page.tsx b/challenge-3-frontend/app/yield-farm/page.tsx index b77996d..48fb0bc 100644 --- a/challenge-3-frontend/app/yield-farm/page.tsx +++ b/challenge-3-frontend/app/yield-farm/page.tsx @@ -1,18 +1,16 @@ "use client"; import SigpassKit from "@/components/sigpasskit"; -import Link from "next/link"; +import YieldFarmInteraction from "@/components/yield"; +import Navbar from "@/components/navbar"; export default function WalletPage() { return (
    -
    - Home - Wallet - Send transaction - Write contract -
    -

    Wallet

    + +

    Yield farm

    +
    + ); } \ No newline at end of file diff --git a/challenge-3-frontend/components/erc20.tsx b/challenge-3-frontend/components/erc20.tsx new file mode 100644 index 0000000..0457a08 --- /dev/null +++ b/challenge-3-frontend/components/erc20.tsx @@ -0,0 +1,596 @@ +"use client"; + +import { useState, useEffect } from "react"; +import { + useWriteContract, + useWaitForTransactionReceipt, + useAccount, + useChainId, + useSwitchChain, +} from "wagmi"; +import { createPublicClient, http, Address } from "viem"; +import { parseUnits, isAddress } from "viem"; +import { + Ban, + ExternalLink, + ChevronDown, + X, + Hash, + LoaderCircle, + CircleCheck, +} from "lucide-react"; +import { z } from "zod"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { useForm } from "react-hook-form"; +import { Button } from "@/components/ui/button"; +import { + Form, + FormControl, + FormDescription, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "@/components/ui/form"; +import { Input } from "@/components/ui/input"; +import { useMediaQuery } from "@/hooks/use-media-query"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogFooter, + DialogTitle, + DialogTrigger, + DialogClose, +} from "@/components/ui/dialog"; +import { + Drawer, + DrawerClose, + DrawerContent, + DrawerDescription, + DrawerFooter, + DrawerHeader, + DrawerTitle, + DrawerTrigger, +} from "@/components/ui/drawer"; +import { truncateHash } from "@/lib/utils"; +import CopyButton from "@/components/copy-button"; +import { getSigpassWallet } from "@/lib/sigpass"; +import { westendAssetHub } from "@/app/providers"; +import { useAtomValue } from "jotai"; +import { addressAtom } from "@/components/sigpasskit"; +import { config, localConfig } from "@/app/providers"; + +// Create publicClient for Westend Asset Hub +const publicClient = createPublicClient({ + chain: westendAssetHub, + transport: http(westendAssetHub.rpcUrls.default.http[0]), +}); + +// IMockERC20 interface ABI +const MOCK_ERC20_ABI = [ + { + inputs: [ + { internalType: "address", name: "to", type: "address" }, + { internalType: "uint256", name: "amount", type: "uint256" }, + ], + name: "mint", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "to", type: "address" }, + { internalType: "uint256", name: "amount", type: "uint256" }, + ], + name: "transfer", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "account", type: "address" }, + ], + name: "balanceOf", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, +]; + +// Schema for token address input +const tokenAddressSchema = z.object({ + tokenAddress: z + .string() + .min(2) + .max(50) + .refine((val) => isAddress(val), { + message: "Invalid Ethereum address format", + }) as z.ZodType
    , +}); + +// Schema for mint and transfer forms +const actionSchema = z.object({ + recipient: z + .string() + .min(2) + .max(50) + .refine((val) => isAddress(val), { + message: "Invalid Ethereum address format", + }) as z.ZodType
    , + amount: z + .string() + .refine((val) => !isNaN(parseFloat(val)) && parseFloat(val) > 0, { + message: "Amount must be a positive number", + }) + .refine((val) => /^\d*\.?\d{0,18}$/.test(val), { + message: "Amount cannot have more than 18 decimal places", + }), +}); + +export default function MockERC20Interaction() { + const { address: userAddress } = useAccount(); + const chainId = useChainId(); + const { switchChain } = useSwitchChain(); + const isDesktop = useMediaQuery("(min-width: 768px)"); + const [open, setOpen] = useState(false); + const [lastError, setLastError] = useState(null); + const sigpassAddress = useAtomValue(addressAtom); + + const isCorrectChain = chainId === westendAssetHub.id; + + // State for token address + const [tokenAddress, setTokenAddress] = useState
    (null); + + // State for balance + const [balance, setBalance] = useState(null); + const [balanceError, setBalanceError] = useState(null); + const [balanceLoading, setBalanceLoading] = useState(false); + + // Token address form + const tokenForm = useForm>({ + resolver: zodResolver(tokenAddressSchema), + defaultValues: { + tokenAddress: "", + }, + }); + + // Mint form + const mintForm = useForm>({ + resolver: zodResolver(actionSchema), + defaultValues: { + recipient: "", + amount: "", + }, + }); + + // Transfer form + const transferForm = useForm>({ + resolver: zodResolver(actionSchema), + defaultValues: { + recipient: "", + amount: "", + }, + }); + + // Fetch balance + const fetchBalance = async () => { + if (!userAddress || !tokenAddress || !isCorrectChain) return; + + try { + setBalanceLoading(true); + const balanceResult = await publicClient.readContract({ + address: tokenAddress, + abi: MOCK_ERC20_ABI, + functionName: "balanceOf", + args: [userAddress], + }); + setBalance(balanceResult as bigint); + setBalanceError(null); + } catch (error: any) { + const errorMsg = error.message.includes("Cannot decode zero data") + ? "Contract not found or balanceOf function missing at this address" + : error.message || "Failed to fetch balance"; + setBalanceError(errorMsg); + setLastError(errorMsg); + console.error("Balance fetch error:", error); + } finally { + setBalanceLoading(false); + } + }; + + // Fetch balance when userAddress or tokenAddress changes + useEffect(() => { + fetchBalance(); + }, [userAddress, tokenAddress, isCorrectChain]); + + // Debug chain and RPC config + useEffect(() => { + console.log("Current Chain ID:", chainId, "Expected Chain ID:", westendAssetHub.id); + console.log("Token Address:", tokenAddress); + console.log("Balance - Data:", balance, "Error:", balanceError, "Loading:", balanceLoading); + // Test RPC connectivity + fetch(westendAssetHub.rpcUrls.default.http[0], { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ jsonrpc: "2.0", method: "eth_blockNumber", params: [], id: 1 }), + }) + .then((res) => res.json()) + .then((data) => console.log("RPC Test Response:", data)) + .catch((err) => console.error("RPC Test Error:", err.message)); + }, [chainId, tokenAddress, balance, balanceError, balanceLoading]); + + // useWriteContract for contract interactions + const { data: hash, error, isPending, writeContractAsync } = useWriteContract({ + config: sigpassAddress ? localConfig : config, + }); + + // Handle token address submission + async function onTokenSubmit(values: z.infer) { + setTokenAddress(values.tokenAddress); + setLastError(null); + tokenForm.reset(); + } + + // Handle mint submission + async function onMintSubmit(values: z.infer) { + if (!userAddress || !tokenAddress || !isCorrectChain) return; + + const amount = parseUnits(values.amount, 18); // Assuming 18 decimals for ERC20 token + + await writeContractAsync({ + address: tokenAddress, + abi: MOCK_ERC20_ABI, + functionName: "mint", + args: [values.recipient, amount], + account: sigpassAddress ? await getSigpassWallet() : undefined, + chainId: westendAssetHub.id, + }); + } + + // Handle transfer submission + async function onTransferSubmit(values: z.infer) { + if (!userAddress || !tokenAddress || !isCorrectChain) return; + + const amount = parseUnits(values.amount, 18); // Assuming 18 decimals for ERC20 token + + await writeContractAsync({ + address: tokenAddress, + abi: MOCK_ERC20_ABI, + functionName: "transfer", + args: [values.recipient, amount], + account: sigpassAddress ? await getSigpassWallet() : undefined, + chainId: westendAssetHub.id, + }); + } + + // Watch for transaction hash and open dialog/drawer + useEffect(() => { + if (hash) { + setOpen(true); + mintForm.reset(); + transferForm.reset(); + } + }, [hash, mintForm, transferForm]); + + // Transaction receipt + const { isLoading: isConfirming, isSuccess: isConfirmed } = useWaitForTransactionReceipt({ + hash, + config: sigpassAddress ? localConfig : config, + }); + + return ( +
    + {!isCorrectChain && ( +
    + Wrong network. Please switch to Westend Asset Hub. + +
    + )} +
    +

    Token Contract

    + {lastError &&

    Error: {lastError}

    } +
    + + ( + + Token Contract Address + + + + Enter the MockERC20 contract address. + + + )} + /> + + + + {tokenAddress && ( +

    + Current Token Address:{" "} + + {truncateHash(tokenAddress)} + + +

    + )} +
    + {tokenAddress && userAddress && ( +
    +

    Token Balance

    + {balanceError ? ( +

    Error: {balanceError}

    + ) : balanceLoading ? ( +

    Loading balance...

    + ) : balance !== null ? ( +

    Balance: {(Number(balance) / 1e18).toFixed(2)} tokens

    + ) : ( +

    Unable to fetch balance.

    + )} +
    + )} + {tokenAddress && userAddress && ( + <> +
    +

    Mint Tokens

    +
    + + ( + + Recipient Address + + + + Address to receive minted tokens. + + + )} + /> + ( + + Amount + + {isDesktop ? ( + + ) : ( + + )} + + Amount of tokens to mint. + + + )} + /> + + + +
    +
    +

    Transfer Tokens

    +
    + + ( + + Recipient Address + + + + Address to receive transferred tokens. + + + )} + /> + ( + + Amount + + {isDesktop ? ( + + ) : ( + + )} + + Amount of tokens to transfer. + + + )} + /> + + + +
    + + )} + {isDesktop ? ( + + + + + + + Transaction Status + + Follow the transaction status below. +
    + {hash ? ( +
    + + Transaction Hash + + {truncateHash(hash)} + + + +
    + ) : ( +
    + + No transaction hash +
    + )} + {!isPending && !isConfirmed && !isConfirming && ( +
    + + No transaction submitted +
    + )} + {isConfirming && ( +
    + + Waiting for confirmation... +
    + )} + {isConfirmed && ( +
    + + Transaction confirmed! +
    + )} + {error && ( +
    + + Error: {error.message} +
    + )} +
    + + + + + +
    +
    + ) : ( + + + + + + + Transaction Status + Follow the transaction status below. + +
    + {hash ? ( +
    + + Transaction Hash + + {truncateHash(hash)} + + + +
    + ) : ( +
    + + No transaction hash +
    + )} + {!isPending && !isConfirmed && !isConfirming && ( +
    + + No transaction submitted +
    + )} + {isConfirming && ( +
    + + Waiting for confirmation... +
    + )} + {isConfirmed && ( +
    + + Transaction confirmed! +
    + )} + {error && ( +
    + + Error: {error.message} +
    + )} +
    + + + + + +
    +
    + )} +
    + ); +} \ No newline at end of file diff --git a/challenge-3-frontend/components/navbar.tsx b/challenge-3-frontend/components/navbar.tsx index d212169..9727515 100644 --- a/challenge-3-frontend/components/navbar.tsx +++ b/challenge-3-frontend/components/navbar.tsx @@ -11,21 +11,27 @@ export default function Navbar() { - Send transaction + Vesting - Write contract + Yield Farm - Mint/Redeem LST Bifrost + Transfer WND + + + Mint / Transfer ERC20 Token ); diff --git a/challenge-3-frontend/components/transfer-wnd.tsx b/challenge-3-frontend/components/transfer-wnd.tsx new file mode 100644 index 0000000..c87044d --- /dev/null +++ b/challenge-3-frontend/components/transfer-wnd.tsx @@ -0,0 +1,352 @@ +"use client"; + +import { useState, useEffect } from "react"; +import { + useSendTransaction, + useWaitForTransactionReceipt, + useAccount, + useChainId, + useSwitchChain, + useBalance, +} from "wagmi"; +import { parseEther, isAddress, Address } from "viem"; +import { z } from "zod"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { useForm } from "react-hook-form"; +import { Button } from "@/components/ui/button"; +import { + Form, + FormControl, + FormDescription, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "@/components/ui/form"; +import { Input } from "@/components/ui/input"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogFooter, + DialogTitle, + DialogTrigger, + DialogClose, +} from "@/components/ui/dialog"; +import { + Drawer, + DrawerClose, + DrawerContent, + DrawerDescription, + DrawerFooter, + DrawerHeader, + DrawerTitle, + DrawerTrigger, +} from "@/components/ui/drawer"; +import { useMediaQuery } from "@/hooks/use-media-query"; +import { + Ban, + ExternalLink, + ChevronDown, + X, + Hash, + LoaderCircle, + CircleCheck, +} from "lucide-react"; +import { truncateHash } from "@/lib/utils"; +import CopyButton from "@/components/copy-button"; +import { westendAssetHub } from "@/app/providers"; + +// Form schema for native token transfer +const transferSchema = z.object({ + recipient: z + .string() + .min(2) + .max(50) + .refine((val) => isAddress(val), { + message: "Invalid Ethereum address format", + }) as z.ZodType
    , + amount: z + .string() + .refine((val) => !isNaN(parseFloat(val)) && parseFloat(val) > 0, { + message: "Amount must be a positive number", + }) + .refine((val) => /^\d*\.?\d{0,12}$/.test(val), { + message: "Amount cannot have more than 12 decimal places", + }), +}); + +export default function TransferNativeToken() { + const { address: userAddress } = useAccount(); + const chainId = useChainId(); + const { switchChain } = useSwitchChain(); + const isDesktop = useMediaQuery("(min-width: 768px)"); + const [open, setOpen] = useState(false); + const isCorrectChain = chainId === westendAssetHub.id; + + // Fetch user balance + const { data: balance, isLoading: balanceLoading, error: balanceError } = useBalance({ + address: userAddress, + chainId: westendAssetHub.id, + }); + + // Form setup + const form = useForm>({ + resolver: zodResolver(transferSchema), + defaultValues: { + recipient: "", + amount: "", + }, + }); + + // Send transaction + const { data: hash, error, isPending, sendTransactionAsync } = useSendTransaction(); + + // Transaction receipt + const { isLoading: isConfirming, isSuccess: isConfirmed } = useWaitForTransactionReceipt({ + hash, + }); + + // Open dialog/drawer on transaction + useEffect(() => { + if (hash) { + setOpen(true); + form.reset(); + } + }, [hash, form]); + + // Submit handler + async function onSubmit(values: z.infer) { + if (!userAddress || !isCorrectChain) return; + + try { + const amount = parseEther(values.amount); // Convert to wei (18 decimals, adjusted for WND) + await sendTransactionAsync({ + to: values.recipient, + value: amount, + chainId: westendAssetHub.id, + }); + } catch (err) { + console.error("Transfer error:", err); + } + } + + // Debug chain and balance + useEffect(() => { + console.log("Current Chain ID:", chainId, "Expected Chain ID:", westendAssetHub.id); + console.log("User Address:", userAddress); + console.log("Balance:", balance ? `${balance.formatted} ${balance.symbol}` : "Loading..."); + if (balanceError) console.error("Balance Error:", balanceError.message); + }, [chainId, userAddress, balance, balanceError]); + + return ( +
    + {!isCorrectChain && ( +
    + Wrong network. Please switch to Westend Asset Hub. + +
    + )} +
    +

    Transfer Native Tokens (WND)

    +

    + Your Balance: {balanceLoading ? ( + "Loading..." + ) : balanceError ? ( + Error: {balanceError.message} + ) : balance ? ( + `${parseFloat(balance.formatted).toFixed(4)} ${balance.symbol}` + ) : ( + "Connect wallet to view balance" + )} +

    +
    + + ( + + Recipient Address + + + + Address to receive WND tokens. + + + )} + /> + ( + + Amount (WND) + + {isDesktop ? ( + + ) : ( + + )} + + Amount of WND to transfer. + + + )} + /> + + + +
    + {isDesktop ? ( + + + + + + + Transaction Status + + Follow the transaction status below. +
    + {hash ? ( +
    + + Transaction Hash + + {truncateHash(hash)} + + + +
    + ) : ( +
    + No transaction hash +
    + )} + {!isPending && !isConfirmed && !isConfirming && ( +
    + No transaction submitted +
    + )} + {isConfirming && ( +
    + Waiting for confirmation... +
    + )} + {isConfirmed && ( +
    + Transaction confirmed! +
    + )} + {error && ( +
    + Error: {error.message} +
    + )} +
    + + + + + +
    +
    + ) : ( + + + + + + + Transaction Status + Follow the transaction status below. + +
    + {hash ? ( +
    + + Transaction Hash + + {truncateHash(hash)} + + + +
    + ) : ( +
    + No transaction hash +
    + )} + {!isPending && !isConfirmed && !isConfirming && ( +
    + No transaction submitted +
    + )} + {isConfirming && ( +
    + Waiting for confirmation... +
    + )} + {isConfirmed && ( +
    + Transaction confirmed! +
    + )} + {error && ( +
    + Error: {error.message} +
    + )} +
    + + + + + +
    +
    + )} +
    + ); +} \ No newline at end of file diff --git a/challenge-3-frontend/components/vesting.tsx b/challenge-3-frontend/components/vesting.tsx new file mode 100644 index 0000000..4bf65d4 --- /dev/null +++ b/challenge-3-frontend/components/vesting.tsx @@ -0,0 +1,959 @@ +/* Previous imports remain unchanged */ +"use client"; + +import { useState, useEffect } from "react"; +import { + useWriteContract, + useWaitForTransactionReceipt, + useAccount, + useChainId, + useSwitchChain, +} from "wagmi"; +import { createPublicClient, http, Address } from "viem"; +import { parseUnits, isAddress } from "viem"; +import { + Ban, + ExternalLink, + ChevronDown, + X, + Hash, + LoaderCircle, + CircleCheck, +} from "lucide-react"; +import { z } from "zod"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { useForm } from "react-hook-form"; +import { Button } from "@/components/ui/button"; +import { + Form, + FormControl, + FormDescription, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "@/components/ui/form"; +import { Input } from "@/components/ui/input"; +import { useMediaQuery } from "@/hooks/use-media-query"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogFooter, + DialogTitle, + DialogTrigger, + DialogClose, +} from "@/components/ui/dialog"; +import { + Drawer, + DrawerClose, + DrawerContent, + DrawerDescription, + DrawerFooter, + DrawerHeader, + DrawerTitle, + DrawerTrigger, +} from "@/components/ui/drawer"; +import { truncateHash } from "@/lib/utils"; +import CopyButton from "@/components/copy-button"; +import { getSigpassWallet } from "@/lib/sigpass"; +import { westendAssetHub } from "@/app/providers"; +import { useAtomValue } from "jotai"; +import { addressAtom } from "@/components/sigpasskit"; +import { config, localConfig } from "@/app/providers"; + +// Create publicClient for Westend Asset Hub +const publicClient = createPublicClient({ + chain: westendAssetHub, + transport: http(westendAssetHub.rpcUrls.default.http[0]), +}); + +// TokenVesting contract ABI +const TOKEN_VESTING_ABI = [ + { + inputs: [ + { internalType: "address", name: "tokenAddress", type: "address" }, + ], + stateMutability: "nonpayable", + type: "constructor", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "beneficiary", type: "address" }, + { indexed: false, internalType: "uint128", name: "amount", type: "uint128" }, + ], + name: "TokensClaimed", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "beneficiary", type: "address" }, + { indexed: false, internalType: "uint128", name: "amount", type: "uint128" }, + ], + name: "VestingScheduleCreated", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "beneficiary", type: "address" }, + ], + name: "Whitelisted", + type: "event", + }, + { + inputs: [ + { internalType: "address", name: "beneficiary", type: "address" }, + ], + name: "addToWhitelist", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "beneficiary", type: "address" }, + ], + name: "calculateVestedAmount", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "claimVestedTokens", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "beneficiary", type: "address" }, + { internalType: "uint128", name: "amount", type: "uint128" }, + { internalType: "uint32", name: "cliffDuration", type: "uint32" }, + { internalType: "uint32", name: "vestingDuration", type: "uint32" }, + { internalType: "uint64", name: "startTime", type: "uint64" }, + ], + name: "createVestingSchedule", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "pause", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "unpause", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "beneficiary", type: "address" }, + ], + name: "revokeVesting", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "beneficiary", type: "address" }, + ], + name: "removeFromWhitelist", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "", type: "address" }, + ], + name: "vestingSchedules", + outputs: [ + { internalType: "uint128", name: "totalAmount", type: "uint128" }, + { internalType: "uint64", name: "startTime", type: "uint64" }, + { internalType: "uint32", name: "cliffDuration", type: "uint32" }, + { internalType: "uint32", name: "vestingDuration", type: "uint32" }, + { internalType: "uint128", name: "amountClaimed", type: "uint128" }, + { internalType: "bool", name: "revoked", type: "bool" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "", type: "address" }, + ], + name: "whitelist", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "paused", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "token", + outputs: [{ internalType: "contract IERC20", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "owner", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, +]; + +// Form schema for creating vesting schedule +const formSchema = z.object({ + beneficiary: z + .string() + .min(2) + .max(50) + .refine((val) => isAddress(val), { + message: "Invalid Ethereum address format", + }) as z.ZodType
    , + amount: z + .string() + .refine((val) => !isNaN(parseFloat(val)) && parseFloat(val) > 0, { + message: "Amount must be a positive number", + }) + .refine((val) => /^\d*\.?\d{0,18}$/.test(val), { + message: "Amount cannot have more than 18 decimal places", + }), + cliffDuration: z + .string() + .refine((val) => !isNaN(parseInt(val)) && parseInt(val) >= 0, { + message: "Cliff duration must be a non-negative integer", + }), + vestingDuration: z + .string() + .refine((val) => !isNaN(parseInt(val)) && parseInt(val) > 0, { + message: "Vesting duration must be a positive integer", + }), + startTime: z + .string() + .optional() + .refine((val) => !val || (!isNaN(parseInt(val)) && parseInt(val) >= 0), { + message: "Start time must be a non-negative integer or empty", + }), +}); + +// Admin form schema for whitelist +const adminSchema = z.object({ + whitelistAddress: z + .string() + .min(2) + .max(50) + .refine((val) => isAddress(val), { + message: "Invalid Ethereum address format", + }) as z.ZodType
    , +}); + +// Utility function to retry readContract +async function readContractWithRetry( + options: { + address: Address; + abi: any; + functionName: string; + args?: any[]; + }, + retries: number = 3, + delay: number = 1000 +): Promise { + for (let attempt = 1; attempt <= retries; attempt++) { + try { + const result = await publicClient.readContract({ + ...options, + }); + return result as T; + } catch (error: any) { + console.error(`Attempt ${attempt} failed for ${options.functionName}:`, error.message); + if (attempt === retries) throw error; + await new Promise((resolve) => setTimeout(resolve, delay)); + } + } + throw new Error(`Failed to read ${options.functionName} after ${retries} attempts`); +} + +export default function TokenVesting() { + const { address: userAddress } = useAccount(); + const chainId = useChainId(); + const { switchChain } = useSwitchChain(); + const isDesktop = useMediaQuery("(min-width: 768px)"); + const [open, setOpen] = useState(false); + const [whitelistSuccess, setWhitelistSuccess] = useState(null); + const [lastError, setLastError] = useState(null); + const sigpassAddress = useAtomValue(addressAtom); + + // Contract address (VERIFY THIS IS CORRECT FOR WESTEND ASSET HUB) + const CONTRACT_ADDRESS = "0xbde21Dc635D265552Ba6Eb80600E2d410D40700C" as Address; + const isCorrectChain = chainId === westendAssetHub.id; + + // State for contract data + const [owner, setOwner] = useState
    (null); + const [ownerError, setOwnerError] = useState(null); + const [ownerLoading, setOwnerLoading] = useState(true); + + const [vestingSchedule, setVestingSchedule] = useState(null); + const [vestingError, setVestingError] = useState(null); + const [vestingLoading, setVestingLoading] = useState(true); + + const [claimableAmount, setClaimableAmount] = useState(null); + const [claimableError, setClaimableError] = useState(null); + const [claimableLoading, setClaimableLoading] = useState(true); + + const [isPaused, setIsPaused] = useState(null); + const [pausedError, setPausedError] = useState(null); + const [pausedLoading, setPausedLoading] = useState(true); + + // Fetch contract data + const fetchContractData = async () => { + setLastError(null); + if (!isCorrectChain) { + setLastError("Please connect to Westend Asset Hub"); + return; + } + + try { + // Fetch owner + setOwnerLoading(true); + const ownerResult = await readContractWithRetry
    ({ + address: CONTRACT_ADDRESS, + abi: TOKEN_VESTING_ABI, + functionName: "owner", + }); + setOwner(ownerResult); + setOwnerError(null); + } catch (error: any) { + const errorMsg = error.message.includes("Cannot decode zero data") + ? "Contract not found or owner function missing at this address" + : error.message || "Failed to fetch owner"; + setOwnerError(errorMsg); + setLastError(errorMsg); + console.error("Owner fetch error:", error); + } finally { + setOwnerLoading(false); + } + + try { + // Fetch vesting schedule + if (userAddress) { + setVestingLoading(true); + const vestingResult = await readContractWithRetry({ + address: CONTRACT_ADDRESS, + abi: TOKEN_VESTING_ABI, + functionName: "vestingSchedules", + args: [userAddress], + }); + setVestingSchedule(vestingResult); + setVestingError(null); + } + } catch (error: any) { + const errorMsg = error.message.includes("Cannot decode zero data") + ? "Contract not found or vestingSchedules function missing" + : error.message || "Failed to fetch vesting schedule"; + setVestingError(errorMsg); + setLastError(errorMsg); + console.error("Vesting fetch error:", error); + } finally { + setVestingLoading(false); + } + + try { + // Fetch claimable amount + if (userAddress) { + setClaimableLoading(true); + const claimableResult = await readContractWithRetry({ + address: CONTRACT_ADDRESS, + abi: TOKEN_VESTING_ABI, + functionName: "calculateVestedAmount", + args: [userAddress], + }); + setClaimableAmount(claimableResult); + setClaimableError(null); + } + } catch (error: any) { + const errorMsg = error.message.includes("Cannot decode zero data") + ? "Contract not found or calculateVestedAmount function missing" + : error.message || "Failed to fetch claimable amount"; + setClaimableError(errorMsg); + setLastError(errorMsg); + console.error("Claimable fetch error:", error); + } finally { + setClaimableLoading(false); + } + + try { + // Fetch paused status + setPausedLoading(true); + const pausedResult = await readContractWithRetry({ + address: CONTRACT_ADDRESS, + abi: TOKEN_VESTING_ABI, + functionName: "paused", + }); + setIsPaused(pausedResult); + setPausedError(null); + } catch (error: any) { + const errorMsg = error.message.includes("Cannot decode zero data") + ? "Contract not found or paused function missing" + : error.message || "Failed to fetch paused status"; + setPausedError(errorMsg); + setLastError(errorMsg); + console.error("Paused fetch error:", error); + } finally { + setPausedLoading(false); + } + }; + + // Fetch data on mount + useEffect(() => { + fetchContractData(); + }, [isCorrectChain, userAddress]); + + // Debug chain, contract, and RPC config + useEffect(() => { + console.log("Current Chain ID:", chainId, "Expected Chain ID:", westendAssetHub.id); + console.log("Contract Address:", CONTRACT_ADDRESS); + console.log("Westend Asset Hub Config:", { + id: westendAssetHub.id, + name: westendAssetHub.name, + rpcUrls: westendAssetHub.rpcUrls, + blockExplorers: westendAssetHub.blockExplorers, + }); + console.log("Owner - Data:", owner, "Error:", ownerError, "Loading:", ownerLoading); + console.log("Vesting - Data:", vestingSchedule, "Error:", vestingError, "Loading:", vestingLoading); + console.log("Claimable - Data:", claimableAmount, "Error:", claimableError, "Loading:", claimableLoading); + console.log("Paused - Data:", isPaused, "Error:", pausedError, "Loading:", pausedLoading); + // Test RPC connectivity + fetch(westendAssetHub.rpcUrls.default.http[0], { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ jsonrpc: "2.0", method: "eth_blockNumber", params: [], id: 1 }), + }) + .then((res) => res.json()) + .then((data) => console.log("RPC Test Response:", data)) + .catch((err) => console.error("RPC Test Error:", err.message)); + }, [ + chainId, + owner, + ownerError, + ownerLoading, + vestingSchedule, + vestingError, + vestingLoading, + claimableAmount, + claimableError, + claimableLoading, + isPaused, + pausedError, + pausedLoading, + ]); + + // useWriteContract for contract interactions + const { data: hash, error, isPending, writeContractAsync } = useWriteContract({ + config: sigpassAddress ? localConfig : config, + }); + + // Vesting schedule form + const form = useForm>({ + resolver: zodResolver(formSchema), + defaultValues: { + beneficiary: "", + amount: "", + cliffDuration: "0", + vestingDuration: "", + startTime: "", + }, + }); + + // Admin form for whitelist + const adminForm = useForm>({ + resolver: zodResolver(adminSchema), + defaultValues: { + whitelistAddress: "", + }, + }); + + // Submit handler for creating vesting schedule + async function onSubmit(values: z.infer) { + if (!userAddress || userAddress !== owner || !isCorrectChain) return; + + const amount = parseUnits(values.amount, 18); // Assuming 18 decimals for ERC20 token + const cliffDuration = parseInt(values.cliffDuration); + const vestingDuration = parseInt(values.vestingDuration); + const startTime = values.startTime ? parseInt(values.startTime) : 0; + + await writeContractAsync({ + address: CONTRACT_ADDRESS, + abi: TOKEN_VESTING_ABI, + functionName: "createVestingSchedule", + args: [values.beneficiary, amount, cliffDuration, vestingDuration, startTime], + account: sigpassAddress ? await getSigpassWallet() : undefined, + chainId: westendAssetHub.id, + }); + } + + // Handler for claiming vested tokens + async function onClaim(id: string) { + if (!claimableAmount || claimableAmount === 0n || !isCorrectChain) return; + + await writeContractAsync({ + address: CONTRACT_ADDRESS, + abi: TOKEN_VESTING_ABI, + functionName: "claimVestedTokens", + args: [id], + account: sigpassAddress ? await getSigpassWallet() : undefined, + chainId: westendAssetHub.id, + }); + } + + // Admin submit handler for whitelist + async function onAdminSubmit(values: z.infer) { + if (!userAddress || userAddress !== owner || !isCorrectChain) return; + + await writeContractAsync({ + address: CONTRACT_ADDRESS, + abi: TOKEN_VESTING_ABI, + functionName: "addToWhitelist", + args: [values.whitelistAddress], + account: sigpassAddress ? await getSigpassWallet() : undefined, + chainId: westendAssetHub.id, + gas: 300_000_000n, // From previous gas limit adjustments + maxFeePerGas: 20_000_000_000_000n, // From previous gas price fix + maxPriorityFeePerGas: 2_000_000_000_000n, + }); + setWhitelistSuccess(`Address ${truncateHash(values.whitelistAddress)} added to whitelist!`); + adminForm.reset(); + } + + // Handler for pausing contract + async function onPause() { + if (!userAddress || userAddress !== owner || !isCorrectChain) return; + + await writeContractAsync({ + address: CONTRACT_ADDRESS, + abi: TOKEN_VESTING_ABI, + functionName: "pause", + args: [], + account: sigpassAddress ? await getSigpassWallet() : undefined, + chainId: westendAssetHub.id, + }); + } + + // Handler for unpausing contract + async function onUnpause() { + if (!userAddress || userAddress !== owner || !isCorrectChain) return; + + await writeContractAsync({ + address: CONTRACT_ADDRESS, + abi: TOKEN_VESTING_ABI, + functionName: "unpause", + args: [], + account: sigpassAddress ? await getSigpassWallet() : undefined, + chainId: westendAssetHub.id, + }); + } + + // Watch for transaction hash and open dialog/drawer + useEffect(() => { + if (hash) { + setOpen(true); + form.reset(); + adminForm.reset(); + setTimeout(() => setWhitelistSuccess(null), 5000); // Clear success message after 5s + } + }, [hash, form, adminForm]); + + // Transaction receipt + const { isLoading: isConfirming, isSuccess: isConfirmed } = useWaitForTransactionReceipt({ + hash, + config: sigpassAddress ? localConfig : config, + }); + + return ( +
    + {!isCorrectChain && ( +
    + Wrong network. Please switch to Westend Asset Hub. + +
    + )} + {isPaused && ( +
    + Contract is paused. No actions allowed except by owner. +
    + )} +
    +

    Contract Information

    + {lastError && ( +

    Last Error: {lastError}

    + )} +

    + Contract Owner: {owner ? ( + + {truncateHash(owner)} + + + ) : ownerError ? ( + Error: {ownerError} + ) : ownerLoading ? ( + "Loading..." + ) : ( + "Unable to fetch owner. Contract may not exist." + )} +

    + +
    + {userAddress === owner && isCorrectChain && ( +
    +

    Admin Actions

    +
    +

    Add to Whitelist

    +
    + + ( + + Address to Whitelist + + + + + Enter the address to allow vesting schedule creation. + + + + )} + /> + + {whitelistSuccess && ( +
    {whitelistSuccess}
    + )} + + +
    +
    +

    Contract Controls

    + + +
    +
    + )} +
    + + ( + + Beneficiary Address + + + + Address to receive vested tokens. + + + )} + /> + ( + + Amount + + {isDesktop ? ( + + ) : ( + + )} + + Amount of tokens to vest. + + + )} + /> + ( + + Cliff Duration (seconds) + + + + Time before vesting begins. + + + )} + /> + ( + + Vesting Duration (seconds) + + + + Total vesting period. + + + )} + /> + ( + + Start Time (Unix timestamp, optional) + + + + Leave empty for current time. + + + )} + /> + + + +
    +

    Vesting Status

    + {vestingSchedule ? ( +
    +

    Total Amount: {(Number(vestingSchedule[0]) / 1e18).toFixed(2)} tokens

    +

    Start Time: {new Date(Number(vestingSchedule[1]) * 1000).toLocaleString()}

    +

    Cliff Duration: {Number(vestingSchedule[2]) / 86400} days

    +

    Vesting Duration: {Number(vestingSchedule[3]) / 86400} days

    +

    Amount Claimed: {(Number(vestingSchedule[4]) / 1e18).toFixed(2)} tokens

    +

    Revoked: {vestingSchedule[5] ? "Yes" : "No"}

    +

    Claimable: {(Number(claimableAmount || 0) / 1e18).toFixed(2)} tokens

    + +
    + ) : vestingError ? ( +

    Error: {vestingError}

    + ) : vestingLoading ? ( +

    Loading vesting schedule...

    + ) : ( +

    No vesting schedule found.

    + )} +
    + {isDesktop ? ( + + + + + + + Transaction Status + + Follow the transaction status below. +
    + {hash ? ( +
    + + Transaction Hash + + {truncateHash(hash)} + + + +
    + ) : ( +
    + No transaction hash +
    + )} + {!isPending && !isConfirmed && !isConfirming && ( +
    + No transaction submitted +
    + )} + {isConfirming && ( +
    + Waiting for confirmation... +
    + )} + {isConfirmed && ( +
    + Transaction confirmed! +
    + )} + {error && ( +
    + Error: {error.message} +
    + )} +
    + + + + + +
    +
    + ) : ( + + + + + + + Transaction Status + Follow the transaction status below. + +
    + {hash ? ( +
    + + Transaction Hash + + {truncateHash(hash)} + + + +
    + ) : ( +
    + No transaction hash +
    + )} + {!isPending && !isConfirmed && !isConfirming && ( +
    + No transaction submitted +
    + )} + {isConfirming && ( +
    + Waiting for confirmation... +
    + )} + {isConfirmed && ( +
    + Transaction confirmed! +
    + )} + {error && ( +
    + Error: {error.message} +
    + )} +
    + + + + + +
    +
    + )} +
    + ); +} \ No newline at end of file diff --git a/challenge-3-frontend/components/write-contract.tsx b/challenge-3-frontend/components/write-contract.tsx index 1c0270b..a7b9cef 100644 --- a/challenge-3-frontend/components/write-contract.tsx +++ b/challenge-3-frontend/components/write-contract.tsx @@ -113,7 +113,7 @@ export default function WriteContract() { config: address ? localConfig : config, }) - const USDC_CONTRACT_ADDRESS = "0xc8576Fb6De558b313afe0302B3fedc6F6447BbEE"; + const USDC_CONTRACT_ADDRESS = "0x237c8A622079a27E99Bc5c6e80f8447a39C3f0dA"; // useReadContracts hook to read contract const { @@ -137,6 +137,8 @@ export default function WriteContract() { const maxBalance = data?.[0]?.result as bigint | undefined; const decimals = data?.[1]?.result as number | undefined; + console.log(maxBalance, decimals); + // form schema for sending transaction const formSchema = z.object({ // address is a required field diff --git a/challenge-3-frontend/components/yield.tsx b/challenge-3-frontend/components/yield.tsx new file mode 100644 index 0000000..c95efa5 --- /dev/null +++ b/challenge-3-frontend/components/yield.tsx @@ -0,0 +1,1296 @@ +"use client"; + +import { useState, useEffect } from "react"; +import { + useWriteContract, + useWaitForTransactionReceipt, + useAccount, + useChainId, + useSwitchChain, +} from "wagmi"; +import { createPublicClient, http, Address } from "viem"; +import { parseUnits } from "viem"; +import { + Ban, + ExternalLink, + ChevronDown, + X, + Hash, + LoaderCircle, + CircleCheck, +} from "lucide-react"; +import { z } from "zod"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { useForm } from "react-hook-form"; +import { Button } from "@/components/ui/button"; +import { + Form, + FormControl, + FormDescription, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "@/components/ui/form"; +import { Input } from "@/components/ui/input"; +import { useMediaQuery } from "@/hooks/use-media-query"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogFooter, + DialogTitle, + DialogTrigger, + DialogClose, +} from "@/components/ui/dialog"; +import { + Drawer, + DrawerClose, + DrawerContent, + DrawerDescription, + DrawerFooter, + DrawerHeader, + DrawerTitle, + DrawerTrigger, +} from "@/components/ui/drawer"; +import { truncateHash } from "@/lib/utils"; +import CopyButton from "@/components/copy-button"; +import { getSigpassWallet } from "@/lib/sigpass"; +import { westendAssetHub } from "@/app/providers"; +import { useAtomValue } from "jotai"; +import { addressAtom } from "@/components/sigpasskit"; +import { config, localConfig } from "@/app/providers"; + +// Hardcoded YieldFarm contract address +const FARM_ADDRESS: Address = "0xb406f1de53ede0d4763a5b26d569ca9dcfea85fb"; // Replace with actual deployed address + +// Create publicClient for Westend Asset Hub +const publicClient = createPublicClient({ + chain: westendAssetHub, + transport: http(westendAssetHub.rpcUrls.default.http[0]), +}); + +// YieldFarm contract ABI +const YIELD_FARM_ABI = [ + { + inputs: [ + { internalType: "address", name: "_lp", type: "address" }, + { internalType: "address", name: "_reward", type: "address" }, + { internalType: "uint256", name: "_rate", type: "uint256" }, + ], + stateMutability: "nonpayable", + type: "constructor", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "user", type: "address" }, + { indexed: false, internalType: "uint256", name: "amount", type: "uint256" }, + ], + name: "EmergencyWithdrawn", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "user", type: "address" }, + { indexed: false, internalType: "uint256", name: "amount", type: "uint256" }, + ], + name: "RewardsClaimed", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "user", type: "address" }, + { indexed: false, internalType: "uint256", name: "amount", type: "uint256" }, + ], + name: "Staked", + type: "event", + }, + { + anonymous: false, + inputs: [ + { indexed: true, internalType: "address", name: "user", type: "address" }, + { indexed: false, internalType: "uint256", name: "amount", type: "uint256" }, + ], + name: "Withdrawn", + type: "event", + }, + { + inputs: [ + { internalType: "address", name: "_user", type: "address" }, + ], + name: "calculateBoostMultiplier", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "claimRewards", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "emergencyWithdraw", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "l", + outputs: [{ internalType: "uint64", name: "", type: "uint64" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "lpToken", + outputs: [{ internalType: "contract IERC20", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "owner", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "_user", type: "address" }, + ], + name: "pendingRewards", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "rPTS", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "rewardPerToken", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "rewardRate", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "rewardToken", + outputs: [{ internalType: "contract IERC20", name: "", type: "address" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "_amt", type: "uint256" }, + ], + name: "stake", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [], + name: "totalStaked", + outputs: [{ internalType: "uint128", name: "", type: "uint128" }], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "_rate", type: "uint256" }, + ], + name: "updateRewardRate", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "", type: "address" }, + ], + name: "userInfo", + outputs: [ + { internalType: "uint128", name: "amount", type: "uint128" }, + { internalType: "uint64", name: "startTime", type: "uint64" }, + { internalType: "uint256", name: "rewardDebt", type: "uint256" }, + { internalType: "uint256", name: "pendingRewards", type: "uint256" }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { internalType: "uint256", name: "_amt", type: "uint256" }, + ], + name: "withdraw", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, +]; + +// IERC20 ABI for token interactions +const IERC20_ABI = [ + { + inputs: [ + { internalType: "address", name: "to", type: "address" }, + { internalType: "uint256", name: "value", type: "uint256" }, + ], + name: "transfer", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "from", type: "address" }, + { internalType: "address", name: "to", type: "address" }, + { internalType: "uint256", name: "value", type: "uint256" }, + ], + name: "transferFrom", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { internalType: "address", name: "account", type: "address" }, + ], + name: "balanceOf", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function", + }, +]; + +// Schema for stake, withdraw, and update reward rate forms +const actionSchema = z.object({ + amount: z + .string() + .refine((val) => !isNaN(parseFloat(val)) && parseFloat(val) > 0, { + message: "Amount must be a positive number", + }) + .refine((val) => /^\d*\.?\d{0,18}$/.test(val), { + message: "Amount cannot have more than 18 decimal places", + }), +}); + +export default function YieldFarmInteraction() { + const { address: userAddress } = useAccount(); + const chainId = useChainId(); + const { switchChain } = useSwitchChain(); + const isDesktop = useMediaQuery("(min-width: 768px)"); + const [open, setOpen] = useState(false); + const [lastError, setLastError] = useState(null); + const sigpassAddress = useAtomValue(addressAtom); + + const isCorrectChain = chainId === westendAssetHub.id; + + // State for contract data + const [lpTokenAddress, setLpTokenAddress] = useState
    (null); + const [rewardTokenAddress, setRewardTokenAddress] = useState
    (null); + const [owner, setOwner] = useState
    (null); + const [ownerError, setOwnerError] = useState(null); + const [ownerLoading, setOwnerLoading] = useState(false); + const [totalStaked, setTotalStaked] = useState(null); + const [totalStakedError, setTotalStakedError] = useState(null); + const [totalStakedLoading, setTotalStakedLoading] = useState(false); + const [rewardRate, setRewardRate] = useState(null); + const [rewardRateError, setRewardRateError] = useState(null); + const [rewardRateLoading, setRewardRateLoading] = useState(false); + const [userInfo, setUserInfo] = useState(null); + const [userInfoError, setUserInfoError] = useState(null); + const [userInfoLoading, setUserInfoLoading] = useState(false); + const [pendingRewards, setPendingRewards] = useState(null); + const [pendingRewardsError, setPendingRewardsError] = useState(null); + const [pendingRewardsLoading, setPendingRewardsLoading] = useState(false); + const [boostMultiplier, setBoostMultiplier] = useState(null); + const [boostMultiplierError, setBoostMultiplierError] = useState(null); + const [boostMultiplierLoading, setBoostMultiplierLoading] = useState(false); + + // State for token balances + const [lpBalance, setLpBalance] = useState(null); + const [lpBalanceError, setLpBalanceError] = useState(null); + const [lpBalanceLoading, setLpBalanceLoading] = useState(false); + const [rewardBalance, setRewardBalance] = useState(null); + const [rewardBalanceError, setRewardBalanceError] = useState(null); + const [rewardBalanceLoading, setRewardBalanceLoading] = useState(false); + + // Stake form + const stakeForm = useForm>({ + resolver: zodResolver(actionSchema), + defaultValues: { + amount: "", + }, + }); + + // Withdraw form + const withdrawForm = useForm>({ + resolver: zodResolver(actionSchema), + defaultValues: { + amount: "", + }, + }); + + // Update reward rate form + const rewardRateForm = useForm>({ + resolver: zodResolver(actionSchema), + defaultValues: { + amount: "", + }, + }); + + // Fetch contract data + const fetchContractData = async () => { + if (!userAddress || !isCorrectChain) return; + + try { + // Fetch owner + setOwnerLoading(true); + const ownerResult = await publicClient.readContract({ + address: FARM_ADDRESS, + abi: YIELD_FARM_ABI, + functionName: "owner", + }); + setOwner(ownerResult as Address); + setOwnerError(null); + } catch (error: any) { + const errorMsg = error.message.includes("Cannot decode zero data") + ? "Contract not found or owner function missing at this address" + : error.message || "Failed to fetch owner"; + setOwnerError(errorMsg); + setLastError(errorMsg); + console.error("Owner fetch error:", error); + } finally { + setOwnerLoading(false); + } + + try { + // Fetch LP token address + const lpTokenResult = await publicClient.readContract({ + address: FARM_ADDRESS, + abi: YIELD_FARM_ABI, + functionName: "lpToken", + }); + setLpTokenAddress(lpTokenResult as Address); + } catch (error: any) { + const errorMsg = error.message.includes("Cannot decode zero data") + ? "Contract not found or lpToken function missing" + : error.message || "Failed to fetch LP token address"; + setLastError(errorMsg); + console.error("LP token fetch error:", error); + } + + try { + // Fetch reward token address + const rewardTokenResult = await publicClient.readContract({ + address: FARM_ADDRESS, + abi: YIELD_FARM_ABI, + functionName: "rewardToken", + }); + setRewardTokenAddress(rewardTokenResult as Address); + } catch (error: any) { + const errorMsg = error.message.includes("Cannot decode zero data") + ? "Contract not found or rewardToken function missing" + : error.message || "Failed to fetch reward token address"; + setLastError(errorMsg); + console.error("Reward token fetch error:", error); + } + + try { + // Fetch total staked + setTotalStakedLoading(true); + const totalStakedResult = await publicClient.readContract({ + address: FARM_ADDRESS, + abi: YIELD_FARM_ABI, + functionName: "totalStaked", + }); + setTotalStaked(totalStakedResult as bigint); + setTotalStakedError(null); + } catch (error: any) { + const errorMsg = error.message.includes("Cannot decode zero data") + ? "Contract not found or totalStaked function missing" + : error.message || "Failed to fetch total staked"; + setTotalStakedError(errorMsg); + setLastError(errorMsg); + console.error("Total staked fetch error:", error); + } finally { + setTotalStakedLoading(false); + } + + try { + // Fetch reward rate + setRewardRateLoading(true); + const rewardRateResult = await publicClient.readContract({ + address: FARM_ADDRESS, + abi: YIELD_FARM_ABI, + functionName: "rewardRate", + }); + setRewardRate(rewardRateResult as bigint); + setRewardRateError(null); + } catch (error: any) { + const errorMsg = error.message.includes("Cannot decode zero data") + ? "Contract not found or rewardRate function missing" + : error.message || "Failed to fetch reward rate"; + setRewardRateError(errorMsg); + setLastError(errorMsg); + console.error("Reward rate fetch error:", error); + } finally { + setRewardRateLoading(false); + } + + try { + // Fetch user info + setUserInfoLoading(true); + const userInfoResult = await publicClient.readContract({ + address: FARM_ADDRESS, + abi: YIELD_FARM_ABI, + functionName: "userInfo", + args: [userAddress], + }); + setUserInfo(userInfoResult); + setUserInfoError(null); + } catch (error: any) { + const errorMsg = error.message.includes("Cannot decode zero data") + ? "Contract not found or userInfo function missing" + : error.message || "Failed to fetch user info"; + setUserInfoError(errorMsg); + setLastError(errorMsg); + console.error("User info fetch error:", error); + } finally { + setUserInfoLoading(false); + } + + try { + // Fetch pending rewards + setPendingRewardsLoading(true); + const pendingRewardsResult = await publicClient.readContract({ + address: FARM_ADDRESS, + abi: YIELD_FARM_ABI, + functionName: "pendingRewards", + args: [userAddress], + }); + setPendingRewards(pendingRewardsResult as bigint); + setPendingRewardsError(null); + } catch (error: any) { + const errorMsg = error.message.includes("Cannot decode zero data") + ? "Contract not found or pendingRewards function missing" + : error.message || "Failed to fetch pending rewards"; + setPendingRewardsError(errorMsg); + setLastError(errorMsg); + console.error("Pending rewards fetch error:", error); + } finally { + setPendingRewardsLoading(false); + } + + try { + // Fetch boost multiplier + setBoostMultiplierLoading(true); + const boostMultiplierResult = await publicClient.readContract({ + address: FARM_ADDRESS, + abi: YIELD_FARM_ABI, + functionName: "calculateBoostMultiplier", + args: [userAddress], + }); + setBoostMultiplier(boostMultiplierResult as bigint); + setBoostMultiplierError(null); + } catch (error: any) { + const errorMsg = error.message.includes("Cannot decode zero data") + ? "Contract not found or calculateBoostMultiplier function missing" + : error.message || "Failed to fetch boost multiplier"; + setBoostMultiplierError(errorMsg); + setLastError(errorMsg); + console.error("Boost multiplier fetch error:", error); + } finally { + setBoostMultiplierLoading(false); + } + }; + + // Fetch token balances + const fetchTokenBalances = async () => { + if (!userAddress || !lpTokenAddress || !rewardTokenAddress || !isCorrectChain) return; + + try { + // Fetch LP token balance + setLpBalanceLoading(true); + const lpBalanceResult = await publicClient.readContract({ + address: lpTokenAddress, + abi: IERC20_ABI, + functionName: "balanceOf", + args: [userAddress], + }); + setLpBalance(lpBalanceResult as bigint); + setLpBalanceError(null); + } catch (error: any) { + const errorMsg = error.message.includes("Cannot decode zero data") + ? "LP token contract not found or balanceOf function missing" + : error.message || "Failed to fetch LP token balance"; + setLpBalanceError(errorMsg); + setLastError(errorMsg); + console.error("LP balance fetch error:", error); + } finally { + setLpBalanceLoading(false); + } + + try { + // Fetch reward token balance + setRewardBalanceLoading(true); + const rewardBalanceResult = await publicClient.readContract({ + address: rewardTokenAddress, + abi: IERC20_ABI, + functionName: "balanceOf", + args: [userAddress], + }); + setRewardBalance(rewardBalanceResult as bigint); + setRewardBalanceError(null); + } catch (error: any) { + const errorMsg = error.message.includes("Cannot decode zero data") + ? "Reward token contract not found or balanceOf function missing" + : error.message || "Failed to fetch reward token balance"; + setRewardBalanceError(errorMsg); + setLastError(errorMsg); + console.error("Reward balance fetch error:", error); + } finally { + setRewardBalanceLoading(false); + } + }; + + // Fetch data when dependencies change + useEffect(() => { + fetchContractData(); + fetchTokenBalances(); + }, [userAddress, lpTokenAddress, rewardTokenAddress, isCorrectChain]); + + // Debug logs + useEffect(() => { + console.log("Current Chain ID:", chainId, "Expected Chain ID:", westendAssetHub.id); + console.log("Farm Address:", FARM_ADDRESS); + console.log("LP Token Address:", lpTokenAddress); + console.log("Reward Token Address:", rewardTokenAddress); + console.log("Owner - Data:", owner, "Error:", ownerError, "Loading:", ownerLoading); + console.log("Total Staked - Data:", totalStaked, "Error:", totalStakedError, "Loading:", totalStakedLoading); + console.log("Reward Rate - Data:", rewardRate, "Error:", rewardRateError, "Loading:", rewardRateLoading); + console.log("User Info - Data:", userInfo, "Error:", userInfoError, "Loading:", userInfoLoading); + console.log("Pending Rewards - Data:", pendingRewards, "Error:", pendingRewardsError, "Loading:", pendingRewardsLoading); + console.log("Boost Multiplier - Data:", boostMultiplier, "Error:", boostMultiplierError, "Loading:", boostMultiplierLoading); + console.log("LP Balance - Data:", lpBalance, "Error:", lpBalanceError, "Loading:", lpBalanceLoading); + console.log("Reward Balance - Data:", rewardBalance, "Error:", rewardBalanceError, "Loading:", rewardBalanceLoading); + // Test RPC connectivity + fetch(westendAssetHub.rpcUrls.default.http[0], { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ jsonrpc: "2.0", method: "eth_blockNumber", params: [], id: 1 }), + }) + .then((res) => res.json()) + .then((data) => console.log("RPC Test Response:", data)) + .catch((err) => console.error("RPC Test Error:", err.message)); + }, [ + chainId, + lpTokenAddress, + rewardTokenAddress, + owner, + ownerError, + ownerLoading, + totalStaked, + totalStakedError, + totalStakedLoading, + rewardRate, + rewardRateError, + rewardRateLoading, + userInfo, + userInfoError, + userInfoLoading, + pendingRewards, + pendingRewardsError, + pendingRewardsLoading, + boostMultiplier, + boostMultiplierError, + boostMultiplierLoading, + lpBalance, + lpBalanceError, + lpBalanceLoading, + rewardBalance, + rewardBalanceError, + rewardBalanceLoading, + ]); + + // useWriteContract for contract interactions + const { data: hash, error, isPending, writeContractAsync } = useWriteContract({ + config: sigpassAddress ? localConfig : config, + }); + + // Handle stake submission + async function onStakeSubmit(values: z.infer) { + if (!userAddress || !isCorrectChain) return; + + const amount = parseUnits(values.amount, 18); // Assuming 18 decimals for LP token + + // Estimate gas + const estimatedGas = await publicClient.estimateContractGas({ + address: FARM_ADDRESS, + abi: YIELD_FARM_ABI, + functionName: "stake", + args: [amount], + account: userAddress, + }); + + // Fetch gas price + const gasPrice = await publicClient.getGasPrice(); + const maxFeePerGas = gasPrice + gasPrice / 2n; // 50% buffer + const maxPriorityFeePerGas = gasPrice / 10n; // 10% of base + + await writeContractAsync({ + address: FARM_ADDRESS, + abi: YIELD_FARM_ABI, + functionName: "stake", + args: [amount], + account: sigpassAddress ? await getSigpassWallet() : undefined, + chainId: westendAssetHub.id, + gas: estimatedGas + estimatedGas / 5n, // 20% buffer + maxFeePerGas, + maxPriorityFeePerGas, + }); + } + + // Handle withdraw submission + async function onWithdrawSubmit(values: z.infer) { + if (!userAddress || !isCorrectChain) return; + + const amount = parseUnits(values.amount, 18); // Assuming 18 decimals for LP token + + // Estimate gas + const estimatedGas = await publicClient.estimateContractGas({ + address: FARM_ADDRESS, + abi: YIELD_FARM_ABI, + functionName: "withdraw", + args: [amount], + account: userAddress, + }); + + // Fetch gas price + const gasPrice = await publicClient.getGasPrice(); + const maxFeePerGas = gasPrice + gasPrice / 2n; + const maxPriorityFeePerGas = gasPrice / 10n; + + await writeContractAsync({ + address: FARM_ADDRESS, + abi: YIELD_FARM_ABI, + functionName: "withdraw", + args: [amount], + account: sigpassAddress ? await getSigpassWallet() : undefined, + chainId: westendAssetHub.id, + gas: estimatedGas + estimatedGas / 5n, + maxFeePerGas, + maxPriorityFeePerGas, + }); + } + + // Handle claim rewards + async function onClaimRewards() { + if (!userAddress || !isCorrectChain) return; + + // Estimate gas + const estimatedGas = await publicClient.estimateContractGas({ + address: FARM_ADDRESS, + abi: YIELD_FARM_ABI, + functionName: "claimRewards", + args: [], + account: userAddress, + }); + + // Fetch gas price + const gasPrice = await publicClient.getGasPrice(); + const maxFeePerGas = gasPrice + gasPrice / 2n; + const maxPriorityFeePerGas = gasPrice / 10n; + + await writeContractAsync({ + address: FARM_ADDRESS, + abi: YIELD_FARM_ABI, + functionName: "claimRewards", + args: [], + account: sigpassAddress ? await getSigpassWallet() : undefined, + chainId: westendAssetHub.id, + gas: estimatedGas + estimatedGas / 5n, + maxFeePerGas, + maxPriorityFeePerGas, + }); + } + + // Handle emergency withdraw + async function onEmergencyWithdraw() { + if (!userAddress || !isCorrectChain) return; + + // Estimate gas + const estimatedGas = await publicClient.estimateContractGas({ + address: FARM_ADDRESS, + abi: YIELD_FARM_ABI, + functionName: "emergencyWithdraw", + args: [], + account: userAddress, + }); + + // Fetch gas price + const gasPrice = await publicClient.getGasPrice(); + const maxFeePerGas = gasPrice + gasPrice / 2n; + const maxPriorityFeePerGas = gasPrice / 10n; + + await writeContractAsync({ + address: FARM_ADDRESS, + abi: YIELD_FARM_ABI, + functionName: "emergencyWithdraw", + args: [], + account: sigpassAddress ? await getSigpassWallet() : undefined, + chainId: westendAssetHub.id, + gas: estimatedGas + estimatedGas / 5n, + maxFeePerGas, + maxPriorityFeePerGas, + }); + } + + // Handle update reward rate submission + async function onRewardRateSubmit(values: z.infer) { + if (!userAddress || userAddress !== owner || !isCorrectChain) return; + + const rate = parseUnits(values.amount, 18); // Assuming 18 decimals for reward rate + + // Estimate gas + const estimatedGas = await publicClient.estimateContractGas({ + address: FARM_ADDRESS, + abi: YIELD_FARM_ABI, + functionName: "updateRewardRate", + args: [rate], + account: userAddress, + }); + + // Fetch gas price + const gasPrice = await publicClient.getGasPrice(); + const maxFeePerGas = gasPrice + gasPrice / 2n; + const maxPriorityFeePerGas = gasPrice / 10n; + + await writeContractAsync({ + address: FARM_ADDRESS, + abi: YIELD_FARM_ABI, + functionName: "updateRewardRate", + args: [rate], + account: sigpassAddress ? await getSigpassWallet() : undefined, + chainId: westendAssetHub.id, + gas: estimatedGas + estimatedGas / 5n, + maxFeePerGas, + maxPriorityFeePerGas, + }); + } + + // Handle approve LP tokens + async function onApprove() { + if (!userAddress || !lpTokenAddress || !isCorrectChain) return; + + const amount = parseUnits("1000", 18); // Approve 1000 tokens + const gasPrice = await publicClient.getGasPrice(); + const maxFeePerGas = gasPrice + gasPrice / 2n; + const maxPriorityFeePerGas = gasPrice / 10n; + + await writeContractAsync({ + address: lpTokenAddress, + abi: IERC20_ABI, + functionName: "approve", + args: [FARM_ADDRESS, amount], + account: sigpassAddress ? await getSigpassWallet() : undefined, + chainId: westendAssetHub.id, + gas: 100_000n, + maxFeePerGas, + maxPriorityFeePerGas, + }); + } + + // Watch for transaction hash and open dialog/drawer + useEffect(() => { + if (hash) { + setOpen(true); + stakeForm.reset(); + withdrawForm.reset(); + rewardRateForm.reset(); + } + }, [hash, stakeForm, withdrawForm, rewardRateForm]); + + // Transaction receipt + const { isLoading: isConfirming, isSuccess: isConfirmed } = useWaitForTransactionReceipt({ + hash, + config: sigpassAddress ? localConfig : config, + }); + + return ( +
    + {!isCorrectChain && ( +
    + Wrong network. Please switch to Westend Asset Hub. + +
    + )} +
    +

    Yield Farm Contract

    + {lastError &&

    Error: {lastError}

    } +

    + Farm Address:{" "} + + {truncateHash(FARM_ADDRESS)} + + +

    + {lpTokenAddress && ( +

    + LP Token Address:{" "} + + {truncateHash(lpTokenAddress)} + + +

    + )} + {rewardTokenAddress && ( +

    + Reward Token Address:{" "} + + {truncateHash(rewardTokenAddress)} + + +

    + )} +
    + {userAddress && ( +
    +

    Farm Information

    +

    + Contract Owner:{" "} + {owner ? ( + + {truncateHash(owner)} + + + ) : ownerError ? ( + Error: {ownerError} + ) : ownerLoading ? ( + "Loading..." + ) : ( + "Unable to fetch owner" + )} +

    +

    + Total Staked:{" "} + {totalStaked !== null ? ( + `${(Number(totalStaked) / 1e18).toFixed(2)} LP tokens` + ) : totalStakedError ? ( + Error: {totalStakedError} + ) : totalStakedLoading ? ( + "Loading..." + ) : ( + "Unable to fetch total staked" + )} +

    +

    + Reward Rate:{" "} + {rewardRate !== null ? ( + `${(Number(rewardRate) / 1e18).toFixed(2)} tokens/second` + ) : rewardRateError ? ( + Error: {rewardRateError} + ) : rewardRateLoading ? ( + "Loading..." + ) : ( + "Unable to fetch reward rate" + )} +

    +
    + )} + {userAddress && ( +
    +

    User Information

    +

    + LP Token Balance:{" "} + {lpBalance !== null ? ( + `${(Number(lpBalance) / 1e18).toFixed(2)} LP tokens` + ) : lpBalanceError ? ( + Error: {lpBalanceError} + ) : lpBalanceLoading ? ( + "Loading..." + ) : ( + "Unable to fetch LP balance" + )} +

    +

    + Reward Token Balance:{" "} + {rewardBalance !== null ? ( + `${(Number(rewardBalance) / 1e18).toFixed(2)} reward tokens` + ) : rewardBalanceError ? ( + Error: {rewardBalanceError} + ) : rewardBalanceLoading ? ( + "Loading..." + ) : ( + "Unable to fetch reward balance" + )} +

    +

    + Staked Amount:{" "} + {userInfo ? ( + `${(Number(userInfo[0]) / 1e18).toFixed(2)} LP tokens` + ) : userInfoError ? ( + Error: {userInfoError} + ) : userInfoLoading ? ( + "Loading..." + ) : ( + "No staked amount" + )} +

    +

    + Pending Rewards:{" "} + {pendingRewards !== null ? ( + `${(Number(pendingRewards) / 1e18).toFixed(2)} reward tokens` + ) : pendingRewardsError ? ( + Error: {pendingRewardsError} + ) : pendingRewardsLoading ? ( + "Loading..." + ) : ( + "No pending rewards" + )} +

    +

    + Boost Multiplier:{" "} + {boostMultiplier !== null ? ( + `${(Number(boostMultiplier) / 100).toFixed(2)}x` + ) : boostMultiplierError ? ( + Error: {boostMultiplierError} + ) : boostMultiplierLoading ? ( + "Loading..." + ) : ( + "No boost multiplier" + )} +

    +
    + )} + {userAddress && userAddress === owner && ( +
    +

    Owner Actions

    +
    + + ( + + New Reward Rate (tokens/second) + + {isDesktop ? ( + + ) : ( + + )} + + Update the reward rate for the farm. + + + )} + /> + + + +
    + )} + {userAddress && ( + <> +
    +

    Stake LP Tokens

    + +
    + + ( + + Amount + + {isDesktop ? ( + + ) : ( + + )} + + Amount of LP tokens to stake. + + + )} + /> + + + +
    +
    +

    Withdraw LP Tokens

    +
    + + ( + + Amount + + {isDesktop ? ( + + ) : ( + + )} + + Amount of LP tokens to withdraw. + + + )} + /> + + + +
    +
    +

    Reward Actions

    + + +
    + + )} + {isDesktop ? ( + + + + + + + Transaction Status + + Follow the transaction status below. +
    + {hash ? ( +
    + + Transaction Hash + + {truncateHash(hash)} + + + +
    + ) : ( +
    + + No transaction hash +
    + )} + {!isPending && !isConfirmed && !isConfirming && ( +
    + + No transaction submitted +
    + )} + {isConfirming && ( +
    + + Waiting for confirmation... +
    + )} + {isConfirmed && ( +
    + + Transaction confirmed! +
    + )} + {error && ( +
    + + Error: {error.message} +
    + )} +
    + + + + + +
    +
    + ) : ( + + + + + + + Transaction Status + Follow the transaction status below. + +
    + {hash ? ( +
    + + Transaction Hash + + {truncateHash(hash)} + + + +
    + ) : ( +
    + + No transaction hash +
    + )} + {!isPending && !isConfirmed && !isConfirming && ( +
    + + No transaction submitted +
    + )} + {isConfirming && ( +
    + + Waiting for confirmation... +
    + )} + {isConfirmed && ( +
    + + Transaction confirmed! +
    + )} + {error && ( +
    + + Error: {error.message} +
    + )} +
    + + + + + +
    +
    + )} +
    + ); +} \ No newline at end of file