diff --git a/README.md b/README.md index b30cad17..9e57437b 100644 --- a/README.md +++ b/README.md @@ -476,7 +476,7 @@ For a given branch, the system maintains the following invariant: That is: -`ActivePool.aggRecordedDebt + ActivePool.calcPendingAggInterest() + DefaultPool.BoldDebt = SUM_i=1_n(TroveManager.getEntireTroveDebt())` +`ActivePool.aggRecordedDebt + ActivePool.calcPendingAggInterest() = SUM_i=1_n(TroveManager.getEntireTroveDebt())` For all `n` Troves in the branch. @@ -492,17 +492,6 @@ Pending aggregate interest is “applied” upon most system actions. That is: This is the only way BOLD is ever minted as interest. Applying individual interest to a Trove updates its recorded debt, but interest is always minted in aggregate. -### Redistribution gains and interest accrual - -The redistribution mechanism from Liquity v1 is carried over to Liquity v2. That is, when the Stability Pool is empty, liquidations are performed by redistributing all debt and collateral from the liquidated Trove(s) to all other active Troves in proportion to their collateral. - -Thus active Troves potentially accrue redistribution debt gains over time. The total redistributed debt is recorded in the `DefaultPool`, and individual Troves' pending redistribution gains are handled in `TroveManager` by the `L_coll` and `L_boldDebt` global trackers. - -Whenever a Trove is touched e.g. by the borrower adjusting debt, its pending redistribution debt gain is "applied" i.e. moved into its recorded debt. - -Pending redistribution gains do **not** accrue interest at aggregate or individual level. All redistribution debt gains are held outside and apart from the interest accrual calculations. This means that a Trove with a relatively high pending redistribution debt gain has a slight advantage: it pays less interest than a Trove with equal entire debt but no pending redistribution gains. - -However, it is possible for anyone to permissionlessly apply a Trove's redistribution gain, i.e. to move them into the Trove's recorded debt via `TroveManager.applyPendingDebt`. This works for batch and non-batched Troves. As such, any unfairness in interest accrual due to redistribution gains can be manually removed. ### Redemption evasion mitigation @@ -533,7 +522,7 @@ The premature adjustment fee works as so: #### Batches and premature adjustment fees ##### Joining a batch -When a trove joins a batch, it pays an upfront fee if the last trove adjustment was done less than the cool period ago. It does’t matter if the Trove and batch have the same interest rate, or when was the last adjustment by the batch. +When a trove joins a batch, it pays an upfront fee if the last trove adjustment was done more than the cool period ago. It does’t matter if the Trove and batch have the same interest rate, or when was the last adjustment by the batch. The last interest rate timestamp will be updated to the time of joining. @@ -1210,8 +1199,8 @@ When `lastGoodPrice` is used to price the LST, the _real_ market price may be hi | Scenario | Consequence | |------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------| -| lastGoodPrice > real market price | Urgent redemptions return too little LST collateral, and may be unprofitable even when BOLD trades at $1 or below | -| lastGoodPrice < real market price | Urgent redemptions return too much LST collateral. They may be too profitable, compared to the market price. | +| lastGoodPrice > market price | Urgent redemptions return too little LST collateral, and may be unprofitable even when BOLD trades at $1 or below | +| lastGoodPrice < market price | Urgent redemptions return too much LST collateral. They may be too profitable, compared to the market price. | #### Solution @@ -1226,29 +1215,15 @@ If the primary oracle setup fails on a given LST branch, then using `lastGoodPri However, a fallback price utilizing the ETH-USD price and the LST's canonical rate could be used. The proposed fallback price calculation for each branch is here: -| Collateral | Primary price calc | Fallback if LST market oracle fails | Fallback if ETH-USD market oracle fails | Fallback if canonical rate fails | -|------------|---------------------------------------------------------|------------------------------------------------------------|-----------------------------------------|----------------------------------| -| WETH | ETH-USD | N/A | lastGoodPrice | N/A | -| WSTETH | STETH-USD * WSTETH-STETH_canonical | min(lastGoodPrice, ETH-USD * WSTETH-STETH_canonical) | lastGoodPrice | lastGoodPrice | -| RETH | min(ETH-USD * RETH-ETH, ETH-USD * RETH-ETH_canonical) | min(lastGoodPrice, ETH-USD * RETH-ETH_canonical) | lastGoodPrice | lastGoodPrice | - - -## Primary LST oracle failure - -During shutdown no borrower ops are allowed, so the main risk of a manipulated canonical rate (inflated price and excess BOLD minting) is eliminated. However, in this case we still take a minimum: `min(lastGoodPrice, ETH-USD * canonical_rate)`. This ensures that if the canonical rate is also manipulated up, we still give urgent redemptions a chance of being profitable (and clearing bad debt) with the `lastGoodPrice`. - -#### STETH-USD oracle failure - -When this oracle fails, the WSTETH PriceFeed switches to pricing WSTETH in USD with `min(lastGoodPrice, ETH-USD * WSTETH-STETH_canonical)`. Since we substitute the failed STETH-USD oracle with the ETH-USD oracle, this inherently assumes that 1 STETH is worth 1 ETH. This is not guaranteed, though its deemed a reasonable assumption during branch shut down, where the system's priority is purely to clear bad debt via urgent redemptions. - -## Canonical rate failure -The LST canonical exchange rate is used in all calculations on all PriceFeeds. If it fails, the branch falls back to using the `lastGoodPrice`, and the branch gets shut down if it is live. If the canonical rate fails _after_ shut down, then the LST PriceFeed switches `lastGoodPrice` and the branch remains shut down. When calling the LST contract externally to fetch the canonical rate, failure is defined as: +| Collateral | Primary price calc | Fallback price calc | +|------------|----------------------------------------------------------------|--------------------------------------------| +| WETH | ETH-USD | lastGoodPrice | +| WSTETH | STETH-USD * WSTETH-STETH_canonical | ETH-USD * WSTETH-STETH_canonical | +| RETH | min(ETH-USD * RETH-ETH, ETH-USD * RETH-ETH_canonical) | ETH-USD * RETH-ETH_canonical | -- The returned rate is 0, or -- The external call reverts +During shutdown no borrower ops are allowed, so the main risk of a manipulated canonical rate (inflated price and excess BOLD minting) is eliminated, and it will be safe to use the canonical rate in conjunction with ETH-USD. -## ETH-USD oracle failure -The ETH-USD market oracle is used in all calculations on all PriceFeeds. If it fails, the branch falls back to using the `lastGoodPrice`, and the branch gets shut down if it is live. If the ETH-USD oracle fails _after_ shut down, then the LST PriceFeed switches `lastGoodPrice` and the branch remains shut down. +Additionally, if the _ETH-USD_ oracle fails after shut down, then the LST PriceFeed should finally switch to the `lastGoodPrice`, and the branch remains shut down. The full logic is implemented in this PR: https://github.com/liquity/bold/pull/393 @@ -1296,7 +1271,7 @@ As mentioned in the interest rate [implementation section](#core-debt-invariant) That is: -`ActivePool.aggRecordedDebt + ActivePool.calcPendingAggInterest() + DefaultBool.BoltDebt = SUM_i=1_n(TroveManager.getEntireTroveDebt())` +`ActivePool.aggRecordedDebt + ActivePool.calcPendingAggInterest() = SUM_i=1_n(TroveManager.getEntireTroveDebt())` For all `n` Troves in the branch. @@ -1379,13 +1354,7 @@ Various solutions have been fielded. Generally, any solution which appears to cr 4. **New multi-collateral Stability Pool.** This pool would absorb some fraction of liquidations from all branches, including shut down branches. -5. **Governance can direct BOLD interest to pay down bad debt**. BOLD interest could be voted to be redirected to paying down the bad debt over time. Although this would not directly clear the bad debt, economically, it should have the same impact - since ultimately, it is the redeemability of _circulating_ BOLD that determines the peg. When an amount equal to the bad debt has been burned, then all circulating BOLD is fully redeemable. See this example: - -image - -This provides a credible way of eventually "filling the hole" created by bad debt (unlike other approaches such as the SP haircut, which depends on SP funds). No additional core system code nor additional governance features are required. Governance may simply propose to redirect BOLD interest to a burn address. - -If there is remaining collateral in the shutdown branch (albeit perhaps at zero USD value) and there are liquidateable Troves, Governance could alternatively vote to direct fees to a permissionless contract that deposits the BOLD to the SP of the shutdown branch and liquidates the Troves against those funds. The resulting collateral gains could, if they have non-zero value, be swapped on a DEX, e.g. for BOLD which could be then directed to LP incentives. All deposits and swaps could be handled permissionlessly by this governance-deployed contract. +5. **Governance can direct BOLD interest to pay down bad debt**. BOLD interest could be voted to be redirected to paying down the bad debt over time. And some additional solutions that may help reduce the chance of bad debt occurring in the first place: @@ -1393,12 +1362,24 @@ And some additional solutions that may help reduce the chance of bad debt occurr 7. **Pro-rata redemptions at TCR < 100% (branch specific, not routed)**. Urgent redemptions are helpful for shrinking the debt of a shut down branch when it is at `TCR > 100%`. However, at `TCR < 100%`, urgent redemptions do not help clear the bad debt. They simply remove all collateral and push it into its final state faster (and in fact, make it slightly worse since they pay a slight collateral bonus). At `TCR < 100%`, we could offer special pro-rata redemptions only on the shut down branch - e.g. at `TCR = 80%`, users may redeem 1 BOLD for $0.80 worth of collateral. This would (in principle) allow someone to completely clear the bad debt via redemption. At first glance it seems unprofitable, but if the redeemer has reason to believe the collateral is underpriced and the price may rebound at some point in future, they may believe it to be profitable to redeem pro-rata. -**Conclusion** +**Chosen solution** -Ultimately, no measures have been implemented in the protocol directly, so the protocol may end up with some bad debt in the case of a branch shut down. Here there is a theoretical possibility that the BOLD supply may be reduced by either users accidentally burning BOLD, or that borrower's interest could be directed by governance to burn BOLD, which would restore its backing over time. +Solution 5 is chosen. Governance can vote to burn the interest under its control by sending the minted BOLD to a burn address. Although this does not directly clear the bad debt, economically, it should have the same impact - since ultimately, it is the redeemability of _circulating_ BOLD that determines the peg. When an amount equal to the bad debt has been burned, then all circulating BOLD is fully redeemable. +See this example: -### 11 - Inaccurate calculation of average branch interest rate +image + +This was chosen over other approaches because: + +- It provides a credible way of eventually "filling the hole" created by bad debt (unlike other approaches such as the SP haircut, which depends on SP funds) +- No additional core system code nor additional governance features are required. Governance can simply propose to redirect BOLD interest to a burn address. + +**Extension: governance can liquidate and swap collateral gains** + +If there is remaining collateral in the shutdown branch (albeit perhaps at zero USD value) and there are liquidateable Troves, Governance could alternatively vote to direct fees to a permissionless contract that deposits the BOLD to the SP of the shutdown branch and liquidates the Troves against those funds. The resulting collateral gains could, if they have non-zero value, be swapped on a DEX, e.g. for BOLD which could be then directed to LP incentives. All deposits and swaps could be handled permissionlessly by this governance-deployed contract. + +### 11 - ## Inaccurate calculation of average branch interest rate `getNewApproxAvgInterestRateFromTroveChange` does not actually calculate the correct average interest rate for a collateral branch. Ideally, we would like to calculate the debt-weighted average interest of all Troves within the branch, upon which our calculation of the upfront fee is based. The desired formula would be: @@ -1458,52 +1439,6 @@ sum(debt_i) While this wouldn't result in the most accurate estimation of the average interest rate either — considering we'd be using outdated debt values sampled at different times for each Trove as weights — at least we would have consistent weights in the numerator and denominator of our weighted average. To implement this though, we'd have to keep track of this modified sum (i.e. the sum of recorded Trove debts) in `ActivePool`, which we currently don't do. -## 12 - Borrower can create multiple unredeemable Troves and evade redemptions - -Brought up by @javalasers on Discord: - -**Description:** - -(credit @javalasers) There's an attack vector where the user can: - -- Create a trove with `MIN_DEBT` of debt and `MIN_ANNUAL_INTEREST_RATE` interest. -- Redeem a tiny amount of BOLD worth of collateral from the protocol -- If they hit their own Trove, They now have a trove paying the min interest but with `debt < MIN_DEBT`, which (in previous system logic) makes this Trove unredeemable. -- This operation could be repeated in order to create multiple Troves at `debt < MIN_DEBT`, for a total unredeemable debt of ~ `n * MIN_DEBT` - -This has been fixed in this PR: -https://github.com/liquity/bold/pull/426 - -Here is the original impact, pre-fix: - -**Impact:** - -If this attack were profitable, it may break the whole equilibrium and game theory of the user set interest rate. - -Some math should be done, and it heavily depends on gas price, but some considerations: - -- The interest wouldn’t be zero due to the min. interest rate, so eventually the Trove would become redeemable again when it's debt rises above `MIN_DEBT` close to `MIN_DEBT`. So if the aim is to keep it 1 year, at min interest rate of 0.5%, the zombie troves should have 1,990 BOLD debt. -- To set it up `~2n` txs are needed, where `n ~= total debt / MIN_DEBT` -- There’s an additional `(n-1) * ETH_GAS_COMPENSATION` ETH that needs to be locked up. - -Also, the management of the Trove needs to be considered, so: -- Either they all have a very high CR -> not capital efficient, it’s kind of a hidden cost -- Or then 2n times more gas have to be spent to adjust troves every time if the attacker is trying to have a low CR and actively manage them (for each trove there’s 1 adjustment that brings it up above `MIN_DEBT` and then again a redemption). - -**Potential Solutions** - -1. Keep a pointer to the last redemeed zombie trove, and use that one first when the next redemption happens (h/t @danielattilasimon ). The attack would still work with redistributions - even after having debt reduced to 0 redistributions could result in the attacker's Trove at `debt < MIN_DEBT` but that’s far more unlikely and much harder to perform (with an extra cost of 5% of the SP size, a huge trove to be liquidated could be opened and then go for the redistributions - however, it’s hard, expensive, can’t be done in 1 tx, it depends on ETH fluctuations, on the global TCR...). - -2. When a trove gets redeemed and ends up with non zero debt, automatically set it to the max interest rate (h/t @cvalkan) - -**Chosen solution** - -Solution 1. was implemented in this PR: -https://github.com/liquity/bold/pull/426 - -Note: with this approach, it can happen that a zombie Trove belonging to a batch gets its debt increased to above `MIN_DEBT` due to its batch being updated but without a direct adjustment occurring on the Trove itself - in which case, the Trove remains a zombie and holds the pointer to the last zombie trove, so it will get still redeemed first in the list upon the next redemption. - -However this seems like quite an edge case: the Trove needs to be batched, get partially redeemed, become a zombie, and then the batch updated before the borrower touches it and debt increased to above MIN_DEBT, and then redeemed _again_ as first in the list. The borrower can easily prevent the last step if desired by touching the Trove and updating its debt to `debt > MIN_DEBT` beforehand. ## Requirements diff --git a/contracts/README.md b/contracts/README.md index cf42d0ca..26b6ebf2 100644 --- a/contracts/README.md +++ b/contracts/README.md @@ -27,8 +27,6 @@ $ forge build $ forge test ``` -Run tests with `forge test -vvv` to see the console logs, which will show trove URI data. - ### Format ```shell diff --git a/contracts/src/BorrowerOperations.sol b/contracts/src/BorrowerOperations.sol index d1478df0..3e8e6574 100644 --- a/contracts/src/BorrowerOperations.sol +++ b/contracts/src/BorrowerOperations.sol @@ -128,7 +128,7 @@ contract BorrowerOperations is LiquityBase, AddRemoveManagers, IBorrowerOperatio error BatchInterestRateChangePeriodNotPassed(); error TroveNotOpen(); error TroveNotActive(); - error TroveNotZombie(); + error TroveNotUnredeemable(); error TroveOpen(); error UpfrontFeeTooHigh(); error BelowCriticalThreshold(); @@ -470,7 +470,7 @@ contract BorrowerOperations is LiquityBase, AddRemoveManagers, IBorrowerOperatio _adjustTrove(troveManagerCached, _troveId, troveChange, _maxUpfrontFee); } - function adjustZombieTrove( + function adjustUnredeemableTrove( uint256 _troveId, uint256 _collChange, bool _isCollIncrease, @@ -481,7 +481,7 @@ contract BorrowerOperations is LiquityBase, AddRemoveManagers, IBorrowerOperatio uint256 _maxUpfrontFee ) external override { ITroveManager troveManagerCached = troveManager; - _requireTroveIsZombie(troveManagerCached, _troveId); + _requireTroveIsUnredeemable(troveManagerCached, _troveId); TroveChange memory troveChange; _initTroveChange(troveChange, _collChange, _isCollIncrease, _boldChange, _isDebtIncrease); @@ -520,7 +520,7 @@ contract BorrowerOperations is LiquityBase, AddRemoveManagers, IBorrowerOperatio _requireIsNotInBatch(_troveId); address owner = troveNFT.ownerOf(_troveId); _requireSenderIsOwnerOrInterestManager(_troveId, owner); - _requireInterestRateInDelegateRange(_troveId, _newAnnualInterestRate, owner); + _requireInterestRateInDelegateRange(_troveId, _newAnnualInterestRate); _requireTroveIsActive(troveManagerCached, _troveId); LatestTroveData memory trove = troveManagerCached.getLatestTroveData(_troveId); @@ -650,8 +650,8 @@ contract BorrowerOperations is LiquityBase, AddRemoveManagers, IBorrowerOperatio } } - // Make sure the Trove doesn't end up zombie - // Now the max repayment is capped to stay above MIN_DEBT, so this only applies to adjustZombieTrove + // Make sure the Trove doesn't end up unredeemable + // Now the max repayment is capped to stay above MIN_DEBT, so this only applies to adjustUnredeemableTrove _requireAtLeastMinDebt(vars.newDebt); vars.newICR = LiquityMath._computeCR(vars.newColl, vars.newDebt, vars.price); @@ -787,8 +787,8 @@ contract BorrowerOperations is LiquityBase, AddRemoveManagers, IBorrowerOperatio ); activePool.mintAggInterestAndAccountForTroveChange(change, batchManager); - // If the trove was zombie, and now it’s not anymore, put it back in the list - if (_checkTroveIsZombie(troveManagerCached, _troveId) && trove.entireDebt >= MIN_DEBT) { + // If the trove was unredeemable, and now it’s not anymore, put it back in the list + if (_checkTroveIsUnredeemable(troveManagerCached, _troveId) && trove.entireDebt >= MIN_DEBT) { troveManagerCached.setTroveStatusToActive(_troveId); _reInsertIntoSortedTroves( _troveId, trove.annualInterestRate, _upperHint, _lowerHint, batchManager, batch.annualInterestRate @@ -1287,17 +1287,6 @@ contract BorrowerOperations is LiquityBase, AddRemoveManagers, IBorrowerOperatio } } - function _requireInterestRateInDelegateRange(uint256 _troveId, uint256 _annualInterestRate, address _owner) internal view { - InterestIndividualDelegate memory individualDelegate = interestIndividualDelegateOf[_troveId]; - // We have previously checked that sender is either owner or delegate - // If it’s owner, this restriction doesn’t apply - if (individualDelegate.account == msg.sender) { - _requireInterestRateInRange( - _annualInterestRate, individualDelegate.minInterestRate, individualDelegate.maxInterestRate - ); - } - } - function _requireIsNotInBatch(uint256 _troveId) internal view { if (interestBatchManagerOf[_troveId] != address(0)) { revert TroveInBatch(); @@ -1315,7 +1304,7 @@ contract BorrowerOperations is LiquityBase, AddRemoveManagers, IBorrowerOperatio function _requireTroveIsOpen(ITroveManager _troveManager, uint256 _troveId) internal view { ITroveManager.Status status = _troveManager.getTroveStatus(_troveId); - if (status != ITroveManager.Status.active && status != ITroveManager.Status.zombie) { + if (status != ITroveManager.Status.active && status != ITroveManager.Status.unredeemable) { revert TroveNotOpen(); } } @@ -1327,20 +1316,20 @@ contract BorrowerOperations is LiquityBase, AddRemoveManagers, IBorrowerOperatio } } - function _requireTroveIsZombie(ITroveManager _troveManager, uint256 _troveId) internal view { - if (!_checkTroveIsZombie(_troveManager, _troveId)) { - revert TroveNotZombie(); + function _requireTroveIsUnredeemable(ITroveManager _troveManager, uint256 _troveId) internal view { + if (!_checkTroveIsUnredeemable(_troveManager, _troveId)) { + revert TroveNotUnredeemable(); } } - function _checkTroveIsZombie(ITroveManager _troveManager, uint256 _troveId) internal view returns (bool) { + function _checkTroveIsUnredeemable(ITroveManager _troveManager, uint256 _troveId) internal view returns (bool) { ITroveManager.Status status = _troveManager.getTroveStatus(_troveId); - return status == ITroveManager.Status.zombie; + return status == ITroveManager.Status.unredeemable; } function _requireTroveIsNotOpen(ITroveManager _troveManager, uint256 _troveId) internal view { ITroveManager.Status status = _troveManager.getTroveStatus(_troveId); - if (status == ITroveManager.Status.active || status == ITroveManager.Status.zombie) { + if (status == ITroveManager.Status.active || status == ITroveManager.Status.unredeemable) { revert TroveOpen(); } } @@ -1453,6 +1442,15 @@ contract BorrowerOperations is LiquityBase, AddRemoveManagers, IBorrowerOperatio if (_minInterestRate >= _maxInterestRate) revert MinGeMax(); } + function _requireInterestRateInDelegateRange(uint256 _troveId, uint256 _annualInterestRate) internal view { + InterestIndividualDelegate memory individualDelegate = interestIndividualDelegateOf[_troveId]; + if (individualDelegate.account != address(0)) { + _requireInterestRateInRange( + _annualInterestRate, individualDelegate.minInterestRate, individualDelegate.maxInterestRate + ); + } + } + function _requireInterestRateInBatchManagerRange(address _interestBatchManagerAddress, uint256 _annualInterestRate) internal view diff --git a/contracts/src/Interfaces/IBorrowerOperations.sol b/contracts/src/Interfaces/IBorrowerOperations.sol index e23a0820..d4eb9c61 100644 --- a/contracts/src/Interfaces/IBorrowerOperations.sol +++ b/contracts/src/Interfaces/IBorrowerOperations.sol @@ -67,7 +67,7 @@ interface IBorrowerOperations is ILiquityBase, IAddRemoveManagers { uint256 _maxUpfrontFee ) external; - function adjustZombieTrove( + function adjustUnredeemableTrove( uint256 _troveId, uint256 _collChange, bool _isCollIncrease, diff --git a/contracts/src/Interfaces/ITroveManager.sol b/contracts/src/Interfaces/ITroveManager.sol index 9db8cc66..6dc5ff6f 100644 --- a/contracts/src/Interfaces/ITroveManager.sol +++ b/contracts/src/Interfaces/ITroveManager.sol @@ -18,7 +18,7 @@ interface ITroveManager is ILiquityBase { active, closedByOwner, closedByLiquidation, - zombie + unredeemable } function shutdownTime() external view returns (uint256); @@ -53,8 +53,6 @@ interface ITroveManager is ILiquityBase { function getCurrentICR(uint256 _troveId, uint256 _price) external view returns (uint256); - function lastZombieTroveId() external view returns (uint256); - function batchLiquidateTroves(uint256[] calldata _troveArray) external; function redeemCollateral( @@ -90,7 +88,7 @@ interface ITroveManager is ILiquityBase { uint256 _batchDebt ) external; - // Called from `adjustZombieTrove()` + // Called from `adjustUnredeemableTrove()` function setTroveStatusToActive(uint256 _troveId) external; function onAdjustTroveInterestRate( diff --git a/contracts/src/NFTMetadata/MetadataNFT.sol b/contracts/src/NFTMetadata/MetadataNFT.sol index 73b65f52..80714a4a 100644 --- a/contracts/src/NFTMetadata/MetadataNFT.sol +++ b/contracts/src/NFTMetadata/MetadataNFT.sol @@ -8,8 +8,6 @@ import "./utils/baseSVG.sol"; import "./utils/bauhaus.sol"; import "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol"; -import {Strings} from "openzeppelin-contracts/contracts/utils/Strings.sol"; - import {ITroveManager} from "src/Interfaces/ITroveManager.sol"; interface IMetadataNFT { @@ -17,7 +15,6 @@ interface IMetadataNFT { uint256 _tokenId; address _owner; address _collToken; - address _boldToken; uint256 _collAmount; uint256 _debtAmount; uint256 _interestRate; @@ -38,8 +35,7 @@ contract MetadataNFT is IMetadataNFT { } function uri(TroveData memory _troveData) public view returns (string memory) { - string memory attr = attributes(_troveData); - return json.formattedMetadata(name, description, renderSVGImage(_troveData), attr); + return json.formattedMetadata(name, description, renderSVGImage(_troveData)); } function renderSVGImage(TroveData memory _troveData) internal view returns (string memory) { @@ -49,25 +45,6 @@ contract MetadataNFT is IMetadataNFT { ); } - function attributes(TroveData memory _troveData) public view returns (string memory) { - //include: collateral token address, collateral amount, debt token address, debt amount, interest rate, status - return string.concat( - '[{"trait_type": "Collateral Token", "value": "', - Strings.toHexString(_troveData._collToken), - '"}, {"trait_type": "Collateral Amount", "value": "', - Strings.toString(_troveData._collAmount), - '"}, {"trait_type": "Debt Token", "value": "', - Strings.toHexString(_troveData._boldToken), - '"}, {"trait_type": "Debt Amount", "value": "', - Strings.toString(_troveData._debtAmount), - '"}, {"trait_type": "Interest Rate", "value": "', - Strings.toString(_troveData._interestRate), - '"}, {"trait_type": "Status", "value": "', - _status2Str(_troveData._status), - '"} ]' - ); - } - function dynamicTextComponents(TroveData memory _troveData) public view returns (string memory) { string memory id = LibString.toHexString(_troveData._tokenId); id = string.concat(LibString.slice(id, 0, 6), "...", LibString.slice(id, 38, 42)); @@ -85,7 +62,7 @@ contract MetadataNFT is IMetadataNFT { if (status == ITroveManager.Status.active) return "Active"; if (status == ITroveManager.Status.closedByOwner) return "Closed"; if (status == ITroveManager.Status.closedByLiquidation) return "Liquidated"; - if (status == ITroveManager.Status.zombie) return "Zombie"; + if (status == ITroveManager.Status.unredeemable) return "Unredeemable"; return ""; } } diff --git a/contracts/src/NFTMetadata/utils/JSON.sol b/contracts/src/NFTMetadata/utils/JSON.sol index 9fd422b1..6a80d114 100644 --- a/contracts/src/NFTMetadata/utils/JSON.sol +++ b/contracts/src/NFTMetadata/utils/JSON.sol @@ -10,25 +10,16 @@ library json { string constant DOUBLE_QUOTES = '\\"'; - function formattedMetadata( - string memory name, - string memory description, - string memory svgImg, - string memory attributes - ) internal pure returns (string memory) { + function formattedMetadata(string memory name, string memory description, string memory svgImg) + internal + pure + returns (string memory) + { return string.concat( "data:application/json;base64,", encode( bytes( - string.concat( - "{", - _prop("name", name), - _prop("description", description), - _xmlImage(svgImg), - ',"attributes":', - attributes, - "}" - ) + string.concat("{", _prop("name", name), _prop("description", description), _xmlImage(svgImg), "}") ) ) ); diff --git a/contracts/src/TroveManager.sol b/contracts/src/TroveManager.sol index 274232a2..668116e3 100644 --- a/contracts/src/TroveManager.sol +++ b/contracts/src/TroveManager.sol @@ -111,8 +111,6 @@ contract TroveManager is LiquityBase, ITroveManager, ITroveEvents { // Array of all batch managers - used to fetch them off-chain address[] public batchIds; - uint256 public lastZombieTroveId; - // Error trackers for the trove redistribution calculation uint256 internal lastCollError_Redistribution; uint256 internal lastBoldDebtError_Redistribution; @@ -151,7 +149,6 @@ contract TroveManager is LiquityBase, ITroveManager, ITroveEvents { uint256 oldWeightedRecordedDebt; uint256 newWeightedRecordedDebt; uint256 newStake; - bool isZombieTrove; LatestTroveData trove; LatestBatchData batch; } @@ -455,7 +452,7 @@ contract TroveManager is LiquityBase, ITroveManager, ITroveEvents { } function _isLiquidatableStatus(Status _status) internal pure returns (bool) { - return _status == Status.active || _status == Status.zombie; + return _status == Status.active || _status == Status.unredeemable; } function _batchLiquidateTroves( @@ -666,26 +663,14 @@ contract TroveManager is LiquityBase, ITroveManager, ITroveEvents { bool isTroveInBatch = _singleRedemption.batchAddress != address(0); uint256 newDebt = _applySingleRedemption(_defaultPool, _singleRedemption, isTroveInBatch); - // Make Trove zombie if it's tiny (and it wasn’t already), in order to prevent griefing future (normal, sequential) redemptions + // Make Trove unredeemable if it's tiny, in order to prevent griefing future (normal, sequential) redemptions if (newDebt < MIN_DEBT) { - if (!_singleRedemption.isZombieTrove) { - Troves[_singleRedemption.troveId].status = Status.zombie; - if (isTroveInBatch) { - sortedTroves.removeFromBatch(_singleRedemption.troveId); - } else { - sortedTroves.remove(_singleRedemption.troveId); - } - // If it’s a partial redemption, let’s store a pointer to it so it’s used first in the next one - if (newDebt > 0) { - lastZombieTroveId = _singleRedemption.troveId; - } - } else if (newDebt == 0) { - // Reset last zombie trove pointer if the previous one was fully redeemed now - lastZombieTroveId = 0; + Troves[_singleRedemption.troveId].status = Status.unredeemable; + if (isTroveInBatch) { + sortedTroves.removeFromBatch(_singleRedemption.troveId); + } else { + sortedTroves.remove(_singleRedemption.troveId); } - } else { - // Reset last zombie trove pointer if the previous one ended up above min debt - lastZombieTroveId = 0; } } @@ -745,13 +730,7 @@ contract TroveManager is LiquityBase, ITroveManager, ITroveEvents { uint256 remainingBold = _boldamount; SingleRedemptionValues memory singleRedemption; - // Let’s check if there’s a pending zombie trove from previous redemption - if (lastZombieTroveId != 0) { - singleRedemption.troveId = lastZombieTroveId; - singleRedemption.isZombieTrove = true; - } else { - singleRedemption.troveId = sortedTrovesCached.getLast(); - } + singleRedemption.troveId = sortedTrovesCached.getLast(); address lastBatchUpdatedInterest = address(0); // Loop through the Troves starting from the one with lowest collateral ratio until _amount of Bold is exchanged for collateral @@ -759,13 +738,7 @@ contract TroveManager is LiquityBase, ITroveManager, ITroveEvents { while (singleRedemption.troveId != 0 && remainingBold > 0 && _maxIterations > 0) { _maxIterations--; // Save the uint256 of the Trove preceding the current one - uint256 nextUserToCheck; - if (singleRedemption.isZombieTrove) { - nextUserToCheck = sortedTrovesCached.getLast(); - } else { - nextUserToCheck = sortedTrovesCached.getPrev(singleRedemption.troveId); - } - + uint256 nextUserToCheck = sortedTrovesCached.getPrev(singleRedemption.troveId); // Skip if ICR < 100%, to make sure that redemptions always improve the CR of hit Troves if (getCurrentICR(singleRedemption.troveId, _price) < _100pct) { singleRedemption.troveId = nextUserToCheck; @@ -796,7 +769,6 @@ contract TroveManager is LiquityBase, ITroveManager, ITroveEvents { remainingBold -= singleRedemption.boldLot; singleRedemption.troveId = nextUserToCheck; - singleRedemption.isZombieTrove = false; } // We are removing this condition to prevent blocking redemptions @@ -839,7 +811,7 @@ contract TroveManager is LiquityBase, ITroveManager, ITroveEvents { bool isTroveInBatch = _singleRedemption.batchAddress != address(0); _applySingleRedemption(_defaultPool, _singleRedemption, isTroveInBatch); - // No need to make this Trove zombie if it has tiny debt, since: + // No need to make this Trove unredeemable if it has tiny debt, since: // - This collateral branch has shut down and urgent redemptions are enabled // - Urgent redemptions aren't sequential, so they can't be griefed by tiny Troves. } @@ -1312,9 +1284,6 @@ contract TroveManager is LiquityBase, ITroveManager, ITroveEvents { function setTroveStatusToActive(uint256 _troveId) external { _requireCallerIsBorrowerOperations(); Troves[_troveId].status = Status.active; - if (lastZombieTroveId == _troveId) { - lastZombieTroveId = 0; - } } function onAdjustTroveInterestRate( @@ -1467,8 +1436,6 @@ contract TroveManager is LiquityBase, ITroveManager, ITroveEvents { if (_batchAddress != address(0)) { if (trove.status == Status.active) { sortedTroves.removeFromBatch(_troveId); - } else if (trove.status == Status.zombie && lastZombieTroveId == _troveId) { - lastZombieTroveId = 0; } _removeTroveSharesFromBatch( @@ -1483,8 +1450,6 @@ contract TroveManager is LiquityBase, ITroveManager, ITroveEvents { } else { if (trove.status == Status.active) { sortedTroves.remove(_troveId); - } else if (trove.status == Status.zombie && lastZombieTroveId == _troveId) { - lastZombieTroveId = 0; } } diff --git a/contracts/src/TroveNFT.sol b/contracts/src/TroveNFT.sol index 97440176..c2ffd6ac 100644 --- a/contracts/src/TroveNFT.sol +++ b/contracts/src/TroveNFT.sol @@ -16,7 +16,6 @@ import {ITroveManager} from "./Interfaces/ITroveManager.sol"; contract TroveNFT is ERC721, ITroveNFT { ITroveManager public immutable troveManager; IERC20Metadata internal immutable collToken; - IBoldToken internal immutable boldToken; IMetadataNFT public immutable metadataNFT; @@ -29,7 +28,6 @@ contract TroveNFT is ERC721, ITroveNFT { troveManager = _addressesRegistry.troveManager(); collToken = _addressesRegistry.collToken(); metadataNFT = _addressesRegistry.metadataNFT(); - boldToken = _addressesRegistry.boldToken(); } function tokenURI(uint256 _tokenId) public view override(ERC721, IERC721Metadata) returns (string memory) { @@ -40,7 +38,6 @@ contract TroveNFT is ERC721, ITroveNFT { _tokenId: _tokenId, _owner: ownerOf(_tokenId), _collToken: address(collToken), - _boldToken: address(boldToken), _collAmount: coll, _debtAmount: debt, _interestRate: annualInterestRate, diff --git a/contracts/src/Zappers/GasCompZapper.sol b/contracts/src/Zappers/GasCompZapper.sol index 801892d4..19d11794 100644 --- a/contracts/src/Zappers/GasCompZapper.sol +++ b/contracts/src/Zappers/GasCompZapper.sol @@ -155,7 +155,7 @@ contract GasCompZapper is AddRemoveManagers { _adjustTrovePost(_collChange, _isCollIncrease, _boldChange, _isDebtIncrease, receiver); } - function adjustZombieTroveWithRawETH( + function adjustUnredeemableTroveWithRawETH( uint256 _troveId, uint256 _collChange, bool _isCollIncrease, @@ -166,7 +166,7 @@ contract GasCompZapper is AddRemoveManagers { uint256 _maxUpfrontFee ) external { address receiver = _adjustTrovePre(_troveId, _collChange, _isCollIncrease, _boldChange, _isDebtIncrease); - borrowerOperations.adjustZombieTrove( + borrowerOperations.adjustUnredeemableTrove( _troveId, _collChange, _isCollIncrease, _boldChange, _isDebtIncrease, _upperHint, _lowerHint, _maxUpfrontFee ); _adjustTrovePost(_collChange, _isCollIncrease, _boldChange, _isDebtIncrease, receiver); diff --git a/contracts/src/Zappers/WETHZapper.sol b/contracts/src/Zappers/WETHZapper.sol index a11e58df..eca59bc5 100644 --- a/contracts/src/Zappers/WETHZapper.sol +++ b/contracts/src/Zappers/WETHZapper.sol @@ -143,7 +143,7 @@ contract WETHZapper is AddRemoveManagers { _adjustTrovePost(_collChange, _isCollIncrease, _boldChange, _isDebtIncrease, receiver); } - function adjustZombieTroveWithRawETH( + function adjustUnredeemableTroveWithRawETH( uint256 _troveId, uint256 _collChange, bool _isCollIncrease, @@ -154,7 +154,7 @@ contract WETHZapper is AddRemoveManagers { uint256 _maxUpfrontFee ) external { address payable receiver = _adjustTrovePre(_troveId, _collChange, _isCollIncrease, _boldChange, _isDebtIncrease); - borrowerOperations.adjustZombieTrove( + borrowerOperations.adjustUnredeemableTrove( _troveId, _collChange, _isCollIncrease, _boldChange, _isDebtIncrease, _upperHint, _lowerHint, _maxUpfrontFee ); _adjustTrovePost(_collChange, _isCollIncrease, _boldChange, _isDebtIncrease, receiver); diff --git a/contracts/src/scripts/DeployLiquity2.s.sol b/contracts/src/scripts/DeployLiquity2.s.sol index d487927c..477fcfa7 100644 --- a/contracts/src/scripts/DeployLiquity2.s.sol +++ b/contracts/src/scripts/DeployLiquity2.s.sol @@ -478,12 +478,19 @@ contract DeployLiquity2Script is Script, StdCheats, MetadataDeployment { // deploy zappers (contracts.gasCompZapper, contracts.wethZapper) = - _deployZappers(contracts.addressesRegistry, contracts.collToken, _weth); + _deployZappers(contracts.addressesRegistry, contracts.collToken, _weth); } - function _deployZappers(IAddressesRegistry _addressesRegistry, IERC20 _collToken, IWETH _weth) + function _deployZappers( + IAddressesRegistry _addressesRegistry, + IERC20 _collToken, + IWETH _weth + ) internal - returns (GasCompZapper gasCompZapper, WETHZapper wethZapper) + returns ( + GasCompZapper gasCompZapper, + WETHZapper wethZapper + ) { bool lst = _collToken != _weth; if (lst) { diff --git a/contracts/src/test/AnchoredInvariantsTest.t.sol b/contracts/src/test/AnchoredInvariantsTest.t.sol index e45f3cb9..212b0f5e 100644 --- a/contracts/src/test/AnchoredInvariantsTest.t.sol +++ b/contracts/src/test/AnchoredInvariantsTest.t.sol @@ -1,17 +1,13 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.18; -import {Strings} from "openzeppelin-contracts/contracts/utils/Strings.sol"; - import "./TestContracts/DevTestSetup.sol"; import {BaseInvariantTest} from "./TestContracts/BaseInvariantTest.sol"; import {BaseMultiCollateralTest} from "./TestContracts/BaseMultiCollateralTest.sol"; import {AdjustedTroveProperties, InvariantsTestHandler} from "./TestContracts/InvariantsTestHandler.t.sol"; import {Logging} from "./Utils/Logging.sol"; -import {TroveId} from "./Utils/TroveId.sol"; -contract AnchoredInvariantsTest is Logging, BaseInvariantTest, BaseMultiCollateralTest, TroveId { - using Strings for uint256; +contract AnchoredInvariantsTest is Logging, BaseInvariantTest, BaseMultiCollateralTest { using StringFormatting for uint256; InvariantsTestHandler handler; @@ -484,632 +480,4 @@ contract AnchoredInvariantsTest is Logging, BaseInvariantTest, BaseMultiCollater vm.prank(hope); handler.provideToSP(1, 4.127947448768090932 ether, false); } - - function testSortedTroveSize() external { - uint256 i = 1; - TestDeployer.LiquityContractsDev memory c = branches[i]; - - vm.prank(adam); - handler.addMeToLiquidationBatch(); - - vm.prank(barb); - handler.addMeToLiquidationBatch(); - - vm.prank(adam); - handler.addMeToUrgentRedemptionBatch(); - - vm.prank(adam); - handler.registerBatchManager( - 3, - 0.100944149373120884 ether, - 0.377922952132481818 ether, - 0.343424998629201343 ether, - 0.489955880173256455 ether, - 2070930 - ); - - vm.prank(carl); - handler.addMeToLiquidationBatch(); - - vm.prank(carl); - handler.warp(9_303_785); - - vm.prank(barb); - handler.registerBatchManager( - 1, - 0.301964103682871801 ether, - 0.756908371280377546 ether, - 0.540898165697757771 ether, - 0.000017102564306416 ether, - 27657915 - ); - - vm.prank(fran); - handler.addMeToLiquidationBatch(); - - vm.prank(eric); - handler.addMeToUrgentRedemptionBatch(); - - vm.prank(hope); - handler.addMeToLiquidationBatch(); - - // upper hint: 30979495632948298397104351002742564073201815129975103483277328125306028611241 - // lower hint: 36051278007718023196469061266077621121244014979449590376694871896669965056265 - // upfront fee: 118.231198854524639989 ether - vm.prank(gabe); - handler.openTrove( - 1, 7_591.289850943621327156 ether, 1.900000000017470971 ether, 0.812103428106344175 ether, 1121, 415425919 - ); - - // redemption rate: 0.005000000000000004 ether - // redeemed BOLD: 0.000000000000071705 ether - // redeemed Troves: [ - // [], - // [gabe], - // [], - // [], - // ] - vm.prank(hope); - handler.redeemCollateral(0.000000000000071705 ether, 1); - - // redemption rate: 0.387443853477360594 ether - // redeemed BOLD: 5_896.917877499258624384 ether - // redeemed Troves: [ - // [], - // [gabe], - // [], - // [], - // ] - vm.prank(gabe); - handler.redeemCollateral(5_896.917877499258624384 ether, 1); - - vm.prank(eric); - handler.warp(11_371_761); - - vm.prank(gabe); - handler.registerBatchManager( - 0, - 0.23834235868248997 ether, - 0.761711006198436234 ether, - 0.523368647516059893 ether, - 0.761688376122671962 ether, - 31535998 - ); - - vm.prank(hope); - handler.registerBatchManager( - 2, - 0.036127532604869915 ether, - 0.999999999999999999 ether, - 0.963882428861225203 ether, - 0.848537401570757863 ether, - 29802393 - ); - - vm.prank(eric); - handler.addMeToUrgentRedemptionBatch(); - - // batch manager: hope - // upper hint: 111996671338791781291582287523793567344508255320483065919810498665837663289426 - // lower hint: 37857035535383668733402580992354953018471987882089934484705744026840633200601 - // upfront fee: 1_355.203530437779650125 ether - vm.prank(carl); - handler.openTroveAndJoinInterestBatchManager( - 2, 73_312.036791249214758342 ether, 1.900020510596646286 ether, 40, 115, 737 - ); - - vm.prank(barb); - handler.registerBatchManager( - 0, - 0.955741837871335122 ether, - 0.974535636428930833 ether, - 0.964294359297779033 ether, - 0.000000000000268875 ether, - 3335617 - ); - - vm.prank(gabe); - handler.addMeToLiquidationBatch(); - - // initial deposit: 0 ether - // compounded deposit: 0 ether - // yield gain: 0 ether - // coll gain: 0 ether - // stashed coll: 0 ether - // blocked SP yield: 975.74654191520134809 ether - vm.prank(fran); - handler.provideToSP(2, 12_633.808570846161076142 ether, true); - - // batch manager: adam - // upper hint: 7512901306961997563120107574274771509748256751277397278816998908345777536679 - // lower hint: 27989025468780058605431608942843597971189459457295957311648808450848491056535 - // upfront fee: 166.681364294341638522 ether - vm.prank(carl); - handler.openTroveAndJoinInterestBatchManager( - 3, 25_307.541971224954454066 ether, 2.401194840294921108 ether, 142, 6432363, 25223 - ); - - vm.prank(carl); - handler.addMeToUrgentRedemptionBatch(); - - vm.prank(adam); - handler.addMeToUrgentRedemptionBatch(); - - vm.prank(dana); - handler.warp(8_774_305); - - vm.prank(adam); - handler.warp(3_835); - - vm.prank(eric); - handler.warp(9_078_180); - - // initial deposit: 0 ether - // compounded deposit: 0 ether - // yield gain: 0 ether - // coll gain: 0 ether - // stashed coll: 0 ether - // blocked SP yield: 0 ether - vm.prank(gabe); - handler.provideToSP(2, 5_179.259567321319728284 ether, true); - - // price: 120.905132749610222778 ether - vm.prank(hope); - handler.setPrice(1, 2.100000000000002648 ether); - - vm.prank(barb); - handler.lowerBatchManagementFee(1, 0.000008085711886436 ether); - - vm.prank(hope); - handler.addMeToLiquidationBatch(); - - vm.prank(adam); - handler.addMeToLiquidationBatch(); - - vm.prank(gabe); - handler.addMeToLiquidationBatch(); - - // price: 80.314880400478576408 ether - vm.prank(gabe); - handler.setPrice(1, 1.394988326842136963 ether); - - vm.prank(carl); - handler.warp(1_849_907); - - // upper hint: 84800337471693920904250232874319843718400766719524250287777680170677855896573 - // lower hint: 0 - // upfront fee: 0 ether - // function: adjustZombieTrove() - vm.prank(gabe); - handler.adjustTrove( - 1, - uint8(AdjustedTroveProperties.onlyColl), - 29.524853479148084596 ether, - true, - 0 ether, - true, - 40, - 14, - 4554760 - ); - - info("SortedTroves size: ", c.sortedTroves.getSize().toString()); - info("num troves: ", handler.numTroves(i).toString()); - info("num zombies: ", handler.numZombies(i).toString()); - info("gabe debt: ", c.troveManager.getTroveEntireDebt(addressToTroveId(gabe)).decimal()); - - // upper hint: 0 - // lower hint: 74750724351164404027318726202729770837051588626953680774538886892291438048970 - // upfront fee: 773.037543760336600445 ether - vm.prank(carl); - handler.openTrove( - 0, 40_510.940914935073773948 ether, 2.063402456659389908 ether, 0.995000000000000248 ether, 0, 55487655 - ); - - vm.prank(adam); - handler.registerBatchManager( - 0, - 0.541865737266494949 ether, - 0.672692246806001449 ether, - 0.650860934960147488 ether, - 0.070089828074852802 ether, - 29179158 - ); - - vm.prank(fran); - handler.registerBatchManager( - 1, - 0.566980989185701648 ether, - 0.86881504225021711 ether, - 0.702666683322997409 ether, - 0.667232273668645041 ether, - 7007521 - ); - - vm.prank(dana); - handler.addMeToUrgentRedemptionBatch(); - - // initial deposit: 0 ether - // compounded deposit: 0 ether - // yield gain: 0 ether - // coll gain: 0 ether - // stashed coll: 0 ether - // blocked SP yield: 1_129.588991574293634631 ether - vm.prank(barb); - handler.provideToSP(1, 0.000000000000000002 ether, false); - - info("SortedTroves size: ", c.sortedTroves.getSize().toString()); - info("num troves: ", handler.numTroves(i).toString()); - info("num zombies: ", handler.numZombies(i).toString()); - info("gabe debt: ", c.troveManager.getTroveEntireDebt(addressToTroveId(gabe)).decimal()); - - // redemption rate: 0.184202341360173417 ether - // redeemed BOLD: 66_462.494346928386331338 ether - // redeemed Troves: [ - // [carl], - // [gabe], - // [], - // [carl], - // ] - vm.prank(eric); - handler.redeemCollateral(66_462.49434692838633134 ether, 1); - - info("SortedTroves size: ", c.sortedTroves.getSize().toString()); - info("num troves: ", handler.numTroves(i).toString()); - info("num zombies: ", handler.numZombies(i).toString()); - info("gabe trove Id: ", addressToTroveId(gabe).toString()); - info("gabe debt: ", c.troveManager.getTroveEntireDebt(addressToTroveId(gabe)).decimal()); - assertEq(c.sortedTroves.getSize(), handler.numTroves(i) - handler.numZombies(i), "Wrong SortedTroves size"); - } - - function testAssertLastZombieTroveInABatchHasMoreThanMinDebt() external { - uint256 i = 1; - TestDeployer.LiquityContractsDev memory c = branches[i]; - - vm.prank(adam); - handler.addMeToUrgentRedemptionBatch(); - - vm.prank(hope); - handler.registerBatchManager( - 0, - 0.99500000000072184 ether, - 0.996944021609020651 ether, - 0.99533906344899454 ether, - 0.378970428480541887 ether, - 314055 - ); - - vm.prank(dana); - handler.warp(2_225_439); - - vm.prank(adam); - handler.addMeToUrgentRedemptionBatch(); - - vm.prank(barb); - handler.addMeToUrgentRedemptionBatch(); - - vm.prank(barb); - handler.registerBatchManager( - 2, - 0.995000000000009379 ether, - 0.999999999998128142 ether, - 0.997477804125778004 ether, - 0.000000001035389259 ether, - 10046 - ); - - vm.prank(gabe); - handler.registerBatchManager( - 2, - 0.346476084765605513 ether, - 0.346476084765605514 ether, - 0.346476084765605514 ether, - 0.000000000000000002 ether, - 27010346 - ); - - vm.prank(fran); - handler.warp(19_697_329); - - vm.prank(gabe); - handler.addMeToUrgentRedemptionBatch(); - - vm.prank(fran); - handler.registerBatchManager( - 1, - 0.995000000000019257 ether, - 0.999999999996150378 ether, - 0.999999999226237651 ether, - 0.696688179568702502 ether, - 7641047 - ); - - vm.prank(gabe); - handler.warp(977_685); - - vm.prank(gabe); - handler.addMeToUrgentRedemptionBatch(); - - vm.prank(fran); - handler.addMeToLiquidationBatch(); - - // batch manager: fran - // upper hint: 0 - // lower hint: 60678094901167127062962700790111047491633904950610080336398562382189456360809 - // upfront fee: 242.684833433337541236 ether - vm.prank(gabe); - handler.openTroveAndJoinInterestBatchManager( - 1, 12_654.280610244006254376 ether, 2.145058504746006382 ether, 182, 22444926, 124118903 - ); - - // redemption rate: 0.005 ether - // redeemed BOLD: 0.000000000000017162 ether - // redeemed Troves: [ - // [], - // [gabe], - // [], - // [], - // ] - vm.prank(hope); - info("gabe trove Id: ", addressToTroveId(gabe).toString()); - info("gabe debt: ", c.troveManager.getTroveEntireDebt(addressToTroveId(gabe)).decimal()); - handler.redeemCollateral(0.000000000000017162 ether, 0); - info("gabe trove Id: ", addressToTroveId(gabe).toString()); - info("gabe debt: ", c.troveManager.getTroveEntireDebt(addressToTroveId(gabe)).decimal()); - - // upper hint: 79178440845664423591903906560915994242429107602729190780850212197412640295587 - // lower hint: 0 - // upfront fee: 624.393448965513162837 ether - vm.prank(hope); - handler.openTrove( - 0, 32_721.264734011072612096 ether, 2.333153121000516764 ether, 0.995000000000109949 ether, 52719, 31482 - ); - - // price: 244.435094708283018275 ether - vm.prank(dana); - handler.setPrice(1, 2.621637893811990143 ether); - - vm.prank(carl); - handler.addMeToUrgentRedemptionBatch(); - - // redemption rate: 0.37622704640950591 ether - // redeemed BOLD: 34_333.025174298345667786 ether - // redeemed Troves: [ - // [hope], - // [gabe], - // [], - // [], - // ] - vm.prank(carl); - info("gabe trove Id: ", addressToTroveId(gabe).toString()); - info("gabe debt: ", c.troveManager.getTroveEntireDebt(addressToTroveId(gabe)).decimal()); - handler.redeemCollateral(34_333.025174298345667787 ether, 0); - info("gabe trove Id: ", addressToTroveId(gabe).toString()); - info("gabe debt: ", c.troveManager.getTroveEntireDebt(addressToTroveId(gabe)).decimal()); - - vm.prank(gabe); - handler.addMeToLiquidationBatch(); - - vm.prank(adam); - handler.addMeToLiquidationBatch(); - - // upper hint: hope - // lower hint: hope - // upfront fee: 45.851924869044942133 ether - vm.prank(carl); - handler.openTrove( - 0, 3_111.607048463492852195 ether, 1.16895262626418546 ether, 0.142852735597140811 ether, 1885973, 10937 - ); - - // upper hint: 2646484967802154597987056038088487662712072023062744056283555991417410575365 - // lower hint: 20207836743015961388089283396921182522044498153231052202943306959004515414684 - // upfront fee: 0 ether - // function: addColl() - info("gabe trove Id: ", addressToTroveId(gabe).toString()); - info("gabe debt: ", c.troveManager.getTroveEntireDebt(addressToTroveId(gabe)).decimal()); - vm.prank(gabe); - handler.adjustTrove( - 1, uint8(AdjustedTroveProperties.onlyColl), 3.631424438531681645 ether, true, 0 ether, false, 86, 703, 9499 - ); - info("gabe trove Id: ", addressToTroveId(gabe).toString()); - info("gabe debt: ", c.troveManager.getTroveEntireDebt(addressToTroveId(gabe)).decimal()); - - vm.prank(barb); - handler.lowerBatchManagementFee(2, 0.000000000204221707 ether); - - vm.prank(hope); - handler.addMeToLiquidationBatch(); - - vm.prank(hope); - handler.addMeToLiquidationBatch(); - - vm.prank(hope); - handler.addMeToUrgentRedemptionBatch(); - - // redemption rate: 0.37622704640950591 ether - // redeemed BOLD: 0.000000000000005602 ether - // redeemed Troves: [ - // [carl], - // [gabe], - // [], - // [], - // ] - vm.prank(carl); - info("gabe trove Id: ", addressToTroveId(gabe).toString()); - info("gabe debt: ", c.troveManager.getTroveEntireDebt(addressToTroveId(gabe)).decimal()); - handler.redeemCollateral(0.000000000000005603 ether, 1); - info("gabe trove Id: ", addressToTroveId(gabe).toString()); - info("gabe debt: ", c.troveManager.getTroveEntireDebt(addressToTroveId(gabe)).decimal()); - - vm.prank(fran); - handler.addMeToUrgentRedemptionBatch(); - - vm.prank(dana); - handler.addMeToUrgentRedemptionBatch(); - - vm.prank(dana); - handler.registerBatchManager( - 1, 0.995000000000001129 ether, 1 ether, 0.999999999999799729 ether, 0.000000000000000001 ether, 31535999 - ); - - // redemption rate: 0.718476929948594246 ether - // redeemed BOLD: 5_431.066474911544502914 ether - // redeemed Troves: [ - // [carl], - // [gabe], - // [], - // [], - // ] - vm.prank(barb); - info("gabe trove Id: ", addressToTroveId(gabe).toString()); - info("gabe debt: ", c.troveManager.getTroveEntireDebt(addressToTroveId(gabe)).decimal()); - handler.redeemCollateral(10_313.397298437031513085 ether, 1); - info("gabe trove Id: ", addressToTroveId(gabe).toString()); - info("gabe ent debt: ", c.troveManager.getTroveEntireDebt(addressToTroveId(gabe)).decimal()); - info("gabe rec debt: ", c.troveManager.getTroveDebt(addressToTroveId(gabe)).decimal()); - info("lzti: ", c.troveManager.lastZombieTroveId().toString()); - - vm.prank(dana); - handler.warp(30_167_580); - - info("gabe ent debt: ", c.troveManager.getTroveEntireDebt(addressToTroveId(gabe)).decimal()); - info("gabe rec debt: ", c.troveManager.getTroveDebt(addressToTroveId(gabe)).decimal()); - info("lzti: ", c.troveManager.lastZombieTroveId().toString()); - vm.prank(gabe); - handler.registerBatchManager( - 1, - 0.995000000000002877 ether, - 0.999999999999430967 ether, - 0.996456350847225481 ether, - 0.000000001322368348 ether, - 14343 - ); - info("gabe ent debt 1: ", c.troveManager.getTroveEntireDebt(addressToTroveId(gabe)).decimal()); - info("gabe rec debt 1: ", c.troveManager.getTroveDebt(addressToTroveId(gabe)).decimal()); - - vm.prank(hope); - handler.addMeToLiquidationBatch(); - - // initial deposit: 0 ether - // compounded deposit: 0 ether - // yield gain: 0 ether - // coll gain: 0 ether - // stashed coll: 0 ether - // blocked SP yield: 0 ether - vm.prank(barb); - handler.provideToSP(3, 1_933.156398582065633891 ether, false); - - vm.prank(hope); - handler.addMeToUrgentRedemptionBatch(); - - // initial deposit: 0 ether - // compounded deposit: 0 ether - // yield gain: 0 ether - // coll gain: 0 ether - // stashed coll: 0 ether - // blocked SP yield: 6_368.077020894268536036 ether - vm.prank(hope); - handler.provideToSP(0, 6_184.412833814428802676 ether, true); - - vm.prank(carl); - handler.addMeToLiquidationBatch(); - - // upper hint: 81940996894813545005963650320412669449148720334632109303327864712326705297348 - // lower hint: carl - // upfront fee: 297.236383200558451701 ether - vm.prank(barb); - handler.openTrove( - 0, - 69_695.596747080749922615 ether, - 1.900000000000006402 ether, - 0.153255449436557929 ether, - 1498297936, - 1276315316 - ); - - // upper hint: 0 - // lower hint: 30960623452289762463130736603892188849115197753010878244835568881362241800197 - // upfront fee: 56.245103106642574315 ether - // function: withdrawBold() - vm.prank(hope); - handler.adjustTrove( - 0, - uint8(AdjustedTroveProperties.onlyDebt), - 0 ether, - false, - 7_875.177407392532383015 ether, - true, - 5, - 16648, - 270 - ); - - // batch manager: gabe - // upper hint: gabe - // lower hint: 0 - // upfront fee: 1_261.275141740191589507 ether - vm.prank(adam); - handler.openTroveAndJoinInterestBatchManager( - 1, 66_969.454138225567397381 ether, 2.984784797753777921 ether, 4294967294, 1, 52 - ); - info("gabe ent debt 2: ", c.troveManager.getTroveEntireDebt(addressToTroveId(gabe)).decimal()); - info("gabe rec debt 2: ", c.troveManager.getTroveDebt(addressToTroveId(gabe)).decimal()); - - // batch manager: hope - // upper hint: 0 - // lower hint: barb - // upfront fee: 1_272.067039116734276271 ether - vm.prank(eric); - handler.openTroveAndJoinInterestBatchManager( - 0, 96_538.742068715532219745 ether, 2.762063859567414329 ether, 0, 61578232, 336273331 - ); - - // initial deposit: 6_184.412833814428802676 ether - // compounded deposit: 6_184.412833814428802676 ether - // yield gain: 7_538.471959199501948711 ether - // coll gain: 0 ether - // stashed coll: 0 ether - // blocked SP yield: 0 ether - vm.prank(hope); - handler.provideToSP(0, 0.000000001590447554 ether, true); - - // initial deposit: 0 ether - // compounded deposit: 0 ether - // yield gain: 0 ether - // coll gain: 0 ether - // stashed coll: 0 ether - // blocked SP yield: 0 ether - vm.prank(fran); - handler.provideToSP(3, 180_836.387435487377369461 ether, true); - - vm.prank(fran); - handler.addMeToLiquidationBatch(); - - // initial deposit: 0 ether - // compounded deposit: 0 ether - // yield gain: 0 ether - // coll gain: 0 ether - // stashed coll: 0 ether - // blocked SP yield: 0 ether - vm.prank(eric); - handler.provideToSP(2, 0.000000000000000012 ether, true); - - vm.prank(carl); - handler.addMeToUrgentRedemptionBatch(); - - // redemption rate: 0.00500000000000102 ether - // redeemed BOLD: 0.000000000536305094 ether - // redeemed Troves: [ - // [barb], - // [gabe], - // [], - // [], - // ] - info("gabe trove Id: ", addressToTroveId(gabe).toString()); - info("gabe ent debt e: ", c.troveManager.getTroveEntireDebt(addressToTroveId(gabe)).decimal()); - info("gabe rec debt e: ", c.troveManager.getTroveDebt(addressToTroveId(gabe)).decimal()); - info("lzti: ", c.troveManager.lastZombieTroveId().toString()); - vm.prank(barb); - handler.redeemCollateral(0.000000000536305095 ether, 3); - } } diff --git a/contracts/src/test/HintHelpers.t.sol b/contracts/src/test/HintHelpers.t.sol index 1eb02cba..2d0465b9 100644 --- a/contracts/src/test/HintHelpers.t.sol +++ b/contracts/src/test/HintHelpers.t.sol @@ -16,7 +16,7 @@ contract HintHelpersTest is DevTestSetup { assertEq( uint8(troveManager.getTroveStatus(redeemedTroveId)), - uint8(ITroveManager.Status.zombie), + uint8(ITroveManager.Status.unredeemable), "Redeemed Trove should have become a zombie" ); diff --git a/contracts/src/test/Invariants.t.sol b/contracts/src/test/Invariants.t.sol index 46e7ffb9..d861a11c 100644 --- a/contracts/src/test/Invariants.t.sol +++ b/contracts/src/test/Invariants.t.sol @@ -38,7 +38,7 @@ library ToStringFunctions { if (status == ITroveManager.Status.active) return "ITroveManager.Status.active"; if (status == ITroveManager.Status.closedByOwner) return "ITroveManager.Status.closedByOwner"; if (status == ITroveManager.Status.closedByLiquidation) return "ITroveManager.Status.closedByLiquidation"; - if (status == ITroveManager.Status.zombie) return "ITroveManager.Status.zombie"; + if (status == ITroveManager.Status.unredeemable) return "ITroveManager.Status.unredeemable"; revert("Invalid status"); } } @@ -109,7 +109,6 @@ contract InvariantsTest is Logging, BaseInvariantTest, BaseMultiCollateralTest { TestDeployer.LiquityContractsDev memory c = branches[i]; assertEq(c.troveManager.getTroveIdsCount(), handler.numTroves(i), "Wrong number of Troves"); - assertEq(c.troveManager.lastZombieTroveId(), handler.designatedVictimId(i), "Wrong designated victim"); assertEq(c.sortedTroves.getSize(), handler.numTroves(i) - handler.numZombies(i), "Wrong SortedTroves size"); assertApproxEqAbsDecimal( c.activePool.calcPendingAggInterest(), handler.getPendingInterest(i), 1e-10 ether, 18, "Wrong interest" @@ -187,13 +186,14 @@ contract InvariantsTest is Logging, BaseInvariantTest, BaseMultiCollateralTest { ITroveManager.Status status = c.troveManager.getTroveStatus(troveId); assertTrue( - status == ITroveManager.Status.active || status == ITroveManager.Status.zombie, "Unexpected status" + status == ITroveManager.Status.active || status == ITroveManager.Status.unredeemable, + "Unexpected status" ); if (status == ITroveManager.Status.active) { assertTrue(c.sortedTroves.contains(troveId), "SortedTroves should contain active Troves"); } else { - assertFalse(c.sortedTroves.contains(troveId), "SortedTroves shouldn't contain zombie Troves"); + assertFalse(c.sortedTroves.contains(troveId), "SortedTroves shouldn't contain unredeemable Troves"); } } } diff --git a/contracts/src/test/TestContracts/BaseTest.sol b/contracts/src/test/TestContracts/BaseTest.sol index 2cbded88..d5271a7c 100644 --- a/contracts/src/test/TestContracts/BaseTest.sol +++ b/contracts/src/test/TestContracts/BaseTest.sol @@ -302,7 +302,7 @@ contract BaseTest is TestAccounts, Logging { vm.stopPrank(); } - function adjustZombieTrove( + function adjustUnredeemableTrove( address _account, uint256 _troveId, uint256 _collChange, @@ -312,7 +312,7 @@ contract BaseTest is TestAccounts, Logging { ) public { vm.startPrank(_account); - borrowerOperations.adjustZombieTrove( + borrowerOperations.adjustUnredeemableTrove( _troveId, _collChange, _isCollIncrease, diff --git a/contracts/src/test/TestContracts/DevTestSetup.sol b/contracts/src/test/TestContracts/DevTestSetup.sol index 4ed74043..9ce9d087 100644 --- a/contracts/src/test/TestContracts/DevTestSetup.sol +++ b/contracts/src/test/TestContracts/DevTestSetup.sol @@ -258,26 +258,8 @@ contract DevTestSetup is BaseTest { assertLt(troveManager.getTroveEntireDebt(_troveIDs.B), MIN_DEBT); // Check A and B tagged as Zombie troves - assertEq(uint8(troveManager.getTroveStatus(_troveIDs.A)), uint8(ITroveManager.Status.zombie)); - assertEq(uint8(troveManager.getTroveStatus(_troveIDs.A)), uint8(ITroveManager.Status.zombie)); - } - - function _redeemAndCreateEmptyZombieTrovesAAndB(ABCDEF memory _troveIDs) internal { - // Redeem enough to leave A with 0 debt and B with debt < MIN_DEBT - uint256 redeemFromA = troveManager.getTroveEntireDebt(_troveIDs.A); - uint256 redeemFromB = troveManager.getTroveEntireDebt(_troveIDs.B); - uint256 redeemAmount = redeemFromA + redeemFromB; - - // Fully redeem A and B - redeem(E, redeemAmount); - - // Check A, B has debt == 0 - assertEq(troveManager.getTroveEntireDebt(_troveIDs.A), 0); - assertEq(troveManager.getTroveEntireDebt(_troveIDs.B), 0); - - // Check A and B tagged as Zombie troves - assertEq(uint8(troveManager.getTroveStatus(_troveIDs.A)), uint8(ITroveManager.Status.zombie)); - assertEq(uint8(troveManager.getTroveStatus(_troveIDs.A)), uint8(ITroveManager.Status.zombie)); + assertEq(uint8(troveManager.getTroveStatus(_troveIDs.A)), uint8(ITroveManager.Status.unredeemable)); + assertEq(uint8(troveManager.getTroveStatus(_troveIDs.A)), uint8(ITroveManager.Status.unredeemable)); } function _redeemAndCreateZombieTroveAAndHitB(ABCDEF memory _troveIDs) internal { @@ -294,7 +276,7 @@ contract DevTestSetup is BaseTest { assertGt(troveManager.getTroveEntireDebt(_troveIDs.B), MIN_DEBT); // // Check A is zombie Trove but B is not - assertEq(uint8(troveManager.getTroveStatus(_troveIDs.A)), uint8(ITroveManager.Status.zombie)); + assertEq(uint8(troveManager.getTroveStatus(_troveIDs.A)), uint8(ITroveManager.Status.unredeemable)); assertEq(uint8(troveManager.getTroveStatus(_troveIDs.B)), uint8(ITroveManager.Status.active)); } diff --git a/contracts/src/test/TestContracts/Interfaces/ITroveManagerTester.sol b/contracts/src/test/TestContracts/Interfaces/ITroveManagerTester.sol index 4d234d4c..6ee22a4a 100644 --- a/contracts/src/test/TestContracts/Interfaces/ITroveManagerTester.sol +++ b/contracts/src/test/TestContracts/Interfaces/ITroveManagerTester.sol @@ -40,7 +40,7 @@ interface ITroveManagerTester is ITroveManager { // Trove and batch getters function checkTroveIsActive(uint256 _troveId) external view returns (bool); function checkTroveIsOpen(uint256 _troveId) external view returns (bool); - function checkTroveIsZombie(uint256 _troveId) external view returns (bool); + function checkTroveIsUnredeemable(uint256 _troveId) external view returns (bool); function hasRedistributionGains(uint256 _troveId) external view returns (bool); diff --git a/contracts/src/test/TestContracts/InvariantsTestHandler.t.sol b/contracts/src/test/TestContracts/InvariantsTestHandler.t.sol index 9a22bfe6..617a0bc1 100644 --- a/contracts/src/test/TestContracts/InvariantsTestHandler.t.sol +++ b/contracts/src/test/TestContracts/InvariantsTestHandler.t.sol @@ -143,8 +143,8 @@ contract InvariantsTestHandler is BaseHandler, BaseMultiCollateralTest { uint256 batchManagementFee; Trove trove; bool wasActive; - bool wasZombie; - bool useZombie; + bool wasUnredeemable; + bool useUnredeemable; uint256 maxDebtDec; int256 collDelta; int256 debtDelta; @@ -300,7 +300,6 @@ contract InvariantsTestHandler is BaseHandler, BaseMultiCollateralTest { uint256 totalCollRedeemed; Redeemed[] redeemed; EnumerableAddressSet batchManagers; // batch managers touched by redemption - uint256 newDesignatedVictimId; } struct UrgentRedemptionTransientState { @@ -329,7 +328,7 @@ contract InvariantsTestHandler is BaseHandler, BaseMultiCollateralTest { ITroveManager.Status constant ACTIVE = ITroveManager.Status.active; ITroveManager.Status constant CLOSED_BY_OWNER = ITroveManager.Status.closedByOwner; ITroveManager.Status constant CLOSED_BY_LIQ = ITroveManager.Status.closedByLiquidation; - ITroveManager.Status constant UNREDEEMABLE = ITroveManager.Status.zombie; + ITroveManager.Status constant UNREDEEMABLE = ITroveManager.Status.unredeemable; FunctionCaller immutable _functionCaller; bool immutable _assumeNoExpectedFailures; // vm.assume() away calls that fail extectedly @@ -342,7 +341,6 @@ contract InvariantsTestHandler is BaseHandler, BaseMultiCollateralTest { mapping(uint256 branchIdx => uint256) LIQ_PENALTY_REDIST; // Public ghost variables (per branch, exposed to InvariantsTest) - mapping(uint256 branchIdx => uint256) public designatedVictimId; // ID of zombie Trove that'll be redeemed first mapping(uint256 branchIdx => uint256) public collSurplus; mapping(uint256 branchIdx => uint256) public spBoldDeposits; mapping(uint256 branchIdx => uint256) public spBoldYield; @@ -423,7 +421,7 @@ contract InvariantsTestHandler is BaseHandler, BaseMultiCollateralTest { coll = trove.coll; debt = trove.debt; - status = _isZombie(i, troveId) ? UNREDEEMABLE : ACTIVE; + status = _isUnredeemable(i, troveId) ? UNREDEEMABLE : ACTIVE; batchManager = _batchManagerOf[i][troveId]; } @@ -696,7 +694,7 @@ contract InvariantsTestHandler is BaseHandler, BaseMultiCollateralTest { bool isCollInc, uint256 debtChange, bool isDebtInc, - uint32 useZombieSeed, + uint32 useUnredeemableSeed, uint32 upperHintSeed, uint32 lowerHintSeed ) external { @@ -704,7 +702,7 @@ contract InvariantsTestHandler is BaseHandler, BaseMultiCollateralTest { i = _bound(i, 0, branches.length - 1); v.prop = AdjustedTroveProperties(_bound(prop, 0, uint8(AdjustedTroveProperties._COUNT) - 1)); - useZombieSeed %= 100; + useUnredeemableSeed %= 100; v.upperHint = _pickHint(i, upperHintSeed); v.lowerHint = _pickHint(i, lowerHintSeed); @@ -717,18 +715,18 @@ contract InvariantsTestHandler is BaseHandler, BaseMultiCollateralTest { v.batchManagementFee = v.c.troveManager.getLatestBatchData(v.batchManager).accruedManagementFee; v.trove = _troves[i][v.troveId]; v.wasActive = _isActive(i, v.troveId); - v.wasZombie = _isZombie(i, v.troveId); + v.wasUnredeemable = _isUnredeemable(i, v.troveId); - if (v.wasActive || v.wasZombie) { + if (v.wasActive || v.wasUnredeemable) { // Choose the wrong type of adjustment 1% of the time - if (v.wasZombie) { - v.useZombie = useZombieSeed != 0; + if (v.wasUnredeemable) { + v.useUnredeemable = useUnredeemableSeed != 0; } else { - v.useZombie = useZombieSeed == 0; + v.useUnredeemable = useUnredeemableSeed == 0; } } else { - // Choose with equal probability between normal vs. zombie adjustment - v.useZombie = useZombieSeed < 50; + // Choose with equal probability between normal vs. unredeemable adjustment + v.useUnredeemable = useUnredeemableSeed < 50; } collChange = v.prop != AdjustedTroveProperties.onlyDebt ? _bound(collChange, 0, v.t.entireColl + 1) : 0; @@ -740,7 +738,7 @@ contract InvariantsTestHandler is BaseHandler, BaseMultiCollateralTest { v.$collDelta = v.collDelta * int256(_price[i]) / int256(DECIMAL_PRECISION); v.upfrontFee = hintHelpers.predictAdjustTroveUpfrontFee(i, v.troveId, isDebtInc ? debtChange : 0); if (v.upfrontFee > 0) assertGtDecimal(v.debtDelta, 0, 18, "Only debt increase should incur upfront fee"); - v.functionName = _getAdjustmentFunctionName(v.prop, isCollInc, isDebtInc, v.useZombie); + v.functionName = _getAdjustmentFunctionName(v.prop, isCollInc, isDebtInc, v.useUnredeemable); info("upper hint: ", _hintToString(i, v.upperHint)); info("lower hint: ", _hintToString(i, v.lowerHint)); @@ -755,7 +753,7 @@ contract InvariantsTestHandler is BaseHandler, BaseMultiCollateralTest { isCollInc.toString(), debtChange.decimal(), isDebtInc.toString(), - useZombieSeed.toString(), + useUnredeemableSeed.toString(), upperHintSeed.toString(), lowerHintSeed.toString() ); @@ -767,8 +765,8 @@ contract InvariantsTestHandler is BaseHandler, BaseMultiCollateralTest { vm.prank(msg.sender); try _functionCaller.call( address(v.c.borrowerOperations), - v.useZombie - ? _encodeZombieTroveAdjustment( + v.useUnredeemable + ? _encodeUnredeemableTroveAdjustment( v.troveId, collChange, isCollInc, debtChange, isDebtInc, v.upperHint, v.lowerHint, v.upfrontFee ) : _encodeActiveTroveAdjustment( @@ -781,8 +779,8 @@ contract InvariantsTestHandler is BaseHandler, BaseMultiCollateralTest { // Preconditions assertFalse(isShutdown[i], "Should have failed as branch had been shut down"); assertFalse(v.collDelta == 0 && v.debtDelta == 0, "Should have failed as there was no change"); - if (v.useZombie) assertTrue(v.wasZombie, "Should have failed as Trove wasn't zombie"); - if (!v.useZombie) assertTrue(v.wasActive, "Should have failed as Trove wasn't active"); + if (v.useUnredeemable) assertTrue(v.wasUnredeemable, "Should have failed as Trove wasn't unredeemable"); + if (!v.useUnredeemable) assertTrue(v.wasActive, "Should have failed as Trove wasn't active"); assertLeDecimal(-v.collDelta, int256(v.t.entireColl), 18, "Should have failed as withdrawal > coll"); assertLeDecimal(-v.debtDelta, int256(v.t.entireDebt), 18, "Should have failed as repayment > debt"); v.newDebt = v.t.entireDebt.add(v.debtDelta) + v.upfrontFee; @@ -802,7 +800,6 @@ contract InvariantsTestHandler is BaseHandler, BaseMultiCollateralTest { v.trove.debt = v.trove.debt.add(v.debtDelta) + v.upfrontFee; _troves[i][v.troveId] = v.trove; _zombieTroveIds[i].remove(v.troveId); - if (designatedVictimId[i] == v.troveId) designatedVictimId[i] = 0; // Effects (batch) if (v.batchManager != address(0)) _touchBatch(i, v.batchManager); @@ -820,11 +817,11 @@ contract InvariantsTestHandler is BaseHandler, BaseMultiCollateralTest { assertEqDecimal(v.collDelta, 0, 18, "Shouldn't have failed as there was a coll change"); assertEqDecimal(v.debtDelta, 0, 18, "Shouldn't have failed as there was a debt change"); } else if (selector == BorrowerOperations.TroveNotActive.selector) { - assertFalse(v.useZombie, string.concat("Shouldn't have been thrown by ", v.functionName)); + assertFalse(v.useUnredeemable, string.concat("Shouldn't have been thrown by ", v.functionName)); assertFalse(v.wasActive, "Shouldn't have failed as Trove was active"); - } else if (selector == BorrowerOperations.TroveNotZombie.selector) { - assertTrue(v.useZombie, string.concat("Shouldn't have been thrown by ", v.functionName)); - assertFalse(v.wasZombie, "Shouldn't have failed as Trove was zombie"); + } else if (selector == BorrowerOperations.TroveNotUnredeemable.selector) { + assertTrue(v.useUnredeemable, string.concat("Shouldn't have been thrown by ", v.functionName)); + assertFalse(v.wasUnredeemable, "Shouldn't have failed as Trove was unredeemable"); } else if (selector == BorrowerOperations.CollWithdrawalTooHigh.selector) { assertGtDecimal(-v.collDelta, int256(v.t.entireColl), 18, "Shouldn't have failed as withdrawal <= coll"); } else if (selector == BorrowerOperations.DebtBelowMin.selector) { @@ -1017,7 +1014,6 @@ contract InvariantsTestHandler is BaseHandler, BaseMultiCollateralTest { delete _timeSinceLastTroveInterestRateAdjustment[i][v.troveId]; _troveIds[i].remove(v.troveId); _zombieTroveIds[i].remove(v.troveId); - if (designatedVictimId[i] == v.troveId) designatedVictimId[i] = 0; // Effects (batch) if (v.batchManager != address(0)) { @@ -1116,7 +1112,6 @@ contract InvariantsTestHandler is BaseHandler, BaseMultiCollateralTest { delete _timeSinceLastTroveInterestRateAdjustment[i][troveId]; _troveIds[i].remove(troveId); _zombieTroveIds[i].remove(troveId); - if (designatedVictimId[i] == troveId) designatedVictimId[i] = 0; if (batchManager != address(0)) _batches[i][batchManager].troves.remove(troveId); } @@ -1285,8 +1280,6 @@ contract InvariantsTestHandler is BaseHandler, BaseMultiCollateralTest { } } - designatedVictimId[j] = r[j].newDesignatedVictimId; - // Effects (batches) for (uint256 i = 0; i < r[j].batchManagers.size(); ++i) { _touchBatch(j, r[j].batchManagers.get(i)); @@ -1516,11 +1509,7 @@ contract InvariantsTestHandler is BaseHandler, BaseMultiCollateralTest { // Effects (Trove) v.trove.applyPending(); _troves[i][v.troveId] = v.trove; - - if (v.t.entireDebt >= MIN_DEBT) { - _zombieTroveIds[i].remove(v.troveId); - if (designatedVictimId[i] == v.troveId) designatedVictimId[i] = 0; - } + if (v.t.entireDebt >= MIN_DEBT) _zombieTroveIds[i].remove(v.troveId); // Effects (batch) if (v.batchManager != address(0)) _touchBatch(i, v.batchManager); @@ -2434,12 +2423,12 @@ contract InvariantsTestHandler is BaseHandler, BaseMultiCollateralTest { return _troveIds[i].has(troveId); } - function _isZombie(uint256 i, uint256 troveId) internal view returns (bool) { + function _isUnredeemable(uint256 i, uint256 troveId) internal view returns (bool) { return _zombieTroveIds[i].has(troveId); } function _isActive(uint256 i, uint256 troveId) internal view returns (bool) { - return _isOpen(i, troveId) && !_isZombie(i, troveId); + return _isOpen(i, troveId) && !_isUnredeemable(i, troveId); } function _pickHint(uint256 i, uint256 seed) internal view returns (uint256) { @@ -2643,29 +2632,6 @@ contract InvariantsTestHandler is BaseHandler, BaseMultiCollateralTest { delete _liquidation; } - function _planOneRedemption(uint256 i, uint256 troveId, uint256 remainingAmount, uint256 feePct) - internal - returns (uint256 debtRedeemed) - { - LatestTroveData memory trove = branches[i].troveManager.getLatestTroveData(troveId); - if (_ICR(i, trove) < _100pct) return 0; - - debtRedeemed = Math.min(remainingAmount, trove.entireDebt); - uint256 collRedeemedPlusFee = debtRedeemed * DECIMAL_PRECISION / _price[i]; - uint256 fee = collRedeemedPlusFee * feePct / _100pct; - uint256 collRedeemed = collRedeemedPlusFee - fee; - - mapping(uint256 branchIdx => RedemptionTransientState) storage r = _redemption; - r[i].redeemed.push(Redeemed({troveId: troveId, coll: collRedeemed, debt: debtRedeemed})); - r[i].totalCollRedeemed += collRedeemed; - - address batchManager = _batchManagerOf[i][troveId]; - if (batchManager != address(0)) r[i].batchManagers.add(batchManager); - - uint256 newDebt = trove.entireDebt - debtRedeemed; - r[i].newDesignatedVictimId = 0 < newDebt && newDebt < MIN_DEBT ? troveId : 0; - } - function _planRedemption(uint256 amount, uint256 maxIterationsPerCollateral, uint256 feePct) internal returns (uint256 totalDebtRedeemed, mapping(uint256 branchIdx => RedemptionTransientState) storage r) @@ -2675,43 +2641,51 @@ contract InvariantsTestHandler is BaseHandler, BaseMultiCollateralTest { r = _redemption; // Try in proportion to unbacked - for (uint256 i = 0; i < branches.length; ++i) { - if (isShutdown[i] || _TCR(i) < SCR[i]) continue; - totalProportions += proportions[i] = _getUnbacked(i); + for (uint256 j = 0; j < branches.length; ++j) { + if (isShutdown[j] || _TCR(j) < SCR[j]) continue; + totalProportions += proportions[j] = _getUnbacked(j); } // Fallback: in proportion to branch debt if (totalProportions == 0) { - for (uint256 i = 0; i < branches.length; ++i) { - if (isShutdown[i] || _TCR(i) < SCR[i]) continue; - totalProportions += proportions[i] = _getTotalDebt(i); + for (uint256 j = 0; j < branches.length; ++j) { + if (isShutdown[j] || _TCR(j) < SCR[j]) continue; + totalProportions += proportions[j] = _getTotalDebt(j); } } if (totalProportions == 0) return (0, r); - for (uint256 i = 0; i < branches.length; ++i) { - r[i].newDesignatedVictimId = designatedVictimId[i]; + for (uint256 j = 0; j < branches.length; ++j) { + r[j].attemptedAmount = amount * proportions[j] / totalProportions; + if (r[j].attemptedAmount == 0) continue; - r[i].attemptedAmount = amount * proportions[i] / totalProportions; - if (r[i].attemptedAmount == 0) continue; + TestDeployer.LiquityContractsDev memory c = branches[j]; + uint256 remainingAmount = r[j].attemptedAmount; + uint256 troveId = 0; // "root node" ID - uint256 remainingAmount = r[i].attemptedAmount; - uint256 lastTrove = branches[i].sortedTroves.getPrev(0); + for (uint256 i = 0; i < maxIterationsPerCollateral || maxIterationsPerCollateral == 0; ++i) { + if (remainingAmount == 0) break; - (uint256 troveId, uint256 nextTroveId) = designatedVictimId[i] != 0 - ? (designatedVictimId[i], lastTrove) - : (lastTrove, branches[i].sortedTroves.getPrev(lastTrove)); + troveId = c.sortedTroves.getPrev(troveId); + if (troveId == 0) break; - for (uint256 j = 0; j < maxIterationsPerCollateral || maxIterationsPerCollateral == 0; ++j) { - if (remainingAmount == 0 || troveId == 0) break; + LatestTroveData memory trove = c.troveManager.getLatestTroveData(troveId); + if (_ICR(j, trove) < _100pct) continue; - uint256 debtRedeemed = _planOneRedemption(i, troveId, remainingAmount, feePct); + uint256 debtRedeemed = Math.min(remainingAmount, trove.entireDebt); + uint256 collRedeemedPlusFee = debtRedeemed * DECIMAL_PRECISION / _price[j]; + uint256 fee = collRedeemedPlusFee * feePct / _100pct; + uint256 collRedeemed = collRedeemedPlusFee - fee; + + r[j].redeemed.push(Redeemed({troveId: troveId, coll: collRedeemed, debt: debtRedeemed})); + + address batchManager = _batchManagerOf[j][troveId]; + if (batchManager != address(0)) r[j].batchManagers.add(batchManager); + + r[j].totalCollRedeemed += collRedeemed; totalDebtRedeemed += debtRedeemed; remainingAmount -= debtRedeemed; - - troveId = nextTroveId; - nextTroveId = branches[i].sortedTroves.getPrev(nextTroveId); } } } @@ -2809,10 +2783,10 @@ contract InvariantsTestHandler is BaseHandler, BaseMultiCollateralTest { AdjustedTroveProperties prop, bool isCollIncrease, bool isDebtIncrease, - bool zombie + bool unredeemable ) internal pure returns (string memory) { - if (zombie) { - return "adjustZombieTrove()"; + if (unredeemable) { + return "adjustUnredeemableTrove()"; } if (prop == AdjustedTroveProperties.onlyColl) { @@ -2873,7 +2847,7 @@ contract InvariantsTestHandler is BaseHandler, BaseMultiCollateralTest { revert("Invalid prop"); } - function _encodeZombieTroveAdjustment( + function _encodeUnredeemableTroveAdjustment( uint256 troveId, uint256 collChange, bool isCollIncrease, @@ -2884,7 +2858,7 @@ contract InvariantsTestHandler is BaseHandler, BaseMultiCollateralTest { uint256 maxUpfrontFee ) internal pure returns (bytes memory) { return abi.encodeCall( - IBorrowerOperations.adjustZombieTrove, + IBorrowerOperations.adjustUnredeemableTrove, (troveId, collChange, isCollIncrease, debtChange, isDebtIncrease, upperHint, lowerHint, maxUpfrontFee) ); } @@ -2973,8 +2947,8 @@ contract InvariantsTestHandler is BaseHandler, BaseMultiCollateralTest { return (selector, "BorrowerOperations.TroveNotActive()"); } - if (selector == BorrowerOperations.TroveNotZombie.selector) { - return (selector, "BorrowerOperations.TroveNotZombie()"); + if (selector == BorrowerOperations.TroveNotUnredeemable.selector) { + return (selector, "BorrowerOperations.TroveNotUnredeemable()"); } if (selector == BorrowerOperations.TroveOpen.selector) { diff --git a/contracts/src/test/TestContracts/TroveManagerTester.t.sol b/contracts/src/test/TestContracts/TroveManagerTester.t.sol index eaa73030..863a6345 100644 --- a/contracts/src/test/TestContracts/TroveManagerTester.t.sol +++ b/contracts/src/test/TestContracts/TroveManagerTester.t.sol @@ -152,7 +152,7 @@ contract TroveManagerTester is ITroveManagerTester, TroveManager { function checkTroveIsOpen(uint256 _troveId) public view returns (bool) { Status status = Troves[_troveId].status; - return status == Status.active || status == Status.zombie; + return status == Status.active || status == Status.unredeemable; } function checkTroveIsActive(uint256 _troveId) external view returns (bool) { @@ -160,9 +160,9 @@ contract TroveManagerTester is ITroveManagerTester, TroveManager { return status == Status.active; } - function checkTroveIsZombie(uint256 _troveId) external view returns (bool) { + function checkTroveIsUnredeemable(uint256 _troveId) external view returns (bool) { Status status = Troves[_troveId].status; - return status == Status.zombie; + return status == Status.unredeemable; } function hasRedistributionGains(uint256 _troveId) external view override returns (bool) { diff --git a/contracts/src/test/Utils/TroveId.sol b/contracts/src/test/Utils/TroveId.sol deleted file mode 100644 index fef9f3e8..00000000 --- a/contracts/src/test/Utils/TroveId.sol +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.18; - -contract TroveId { - function addressToTroveId(address _owner, uint256 _ownerIndex) public pure returns (uint256) { - return uint256(keccak256(abi.encode(_owner, _ownerIndex))); - } - - function addressToTroveId(address _owner) public pure returns (uint256) { - return addressToTroveId(_owner, 0); - } -} diff --git a/contracts/src/test/interestBatchManagement.t.sol b/contracts/src/test/interestBatchManagement.t.sol index fe1b11e5..0abc63f1 100644 --- a/contracts/src/test/interestBatchManagement.t.sol +++ b/contracts/src/test/interestBatchManagement.t.sol @@ -114,7 +114,7 @@ contract InterestBatchManagementTest is DevTestSetup { vm.stopPrank(); } - function testCannotSetBatchManagerIfTroveIsZombie() public { + function testCannotSetBatchManagerIfTroveIsUnredeemable() public { registerBatchManager(B); // Open trove @@ -754,7 +754,7 @@ contract InterestBatchManagementTest is DevTestSetup { redeem(A, 500e18); // Check A is zombie - assertEq(uint8(troveManager.getTroveStatus(ATroveId)), uint8(ITroveManager.Status.zombie)); + assertEq(uint8(troveManager.getTroveStatus(ATroveId)), uint8(ITroveManager.Status.unredeemable)); // Fast-forward time vm.warp(block.timestamp + 3650 days); @@ -1135,7 +1135,7 @@ contract InterestBatchManagementTest is DevTestSetup { assertEq(troveData.lastInterestRateAdjTime, block.timestamp, "Wrong interest rate adj time for A"); } - function testAnZombieTroveGoesBackToTheBatch() public { + function testAnUnredeemableTroveGoesBackToTheBatch() public { // A opens trove and joins batch manager B uint256 troveId = openTroveAndJoinBatchManager(A, 100 ether, 2000e18, B, 5e16); @@ -1144,11 +1144,11 @@ contract InterestBatchManagementTest is DevTestSetup { vm.warp(block.timestamp + 10 days); - // C redeems and makes A zombie + // C redeems and makes A unredeemable redeem(C, 1000e18); // A adjusts back to normal - adjustZombieTrove(A, troveId, 0, false, 1000e18, true); + adjustUnredeemableTrove(A, troveId, 0, false, 1000e18, true); assertEq(borrowerOperations.interestBatchManagerOf(troveId), B, "A should be in batch (BO)"); (,,,,,,,, address tmBatchManagerAddress,) = troveManager.Troves(troveId); diff --git a/contracts/src/test/interestIndividualDelegation.t.sol b/contracts/src/test/interestIndividualDelegation.t.sol index f8a8c5b1..e29a1f91 100644 --- a/contracts/src/test/interestIndividualDelegation.t.sol +++ b/contracts/src/test/interestIndividualDelegation.t.sol @@ -102,22 +102,6 @@ contract InterestIndividualDelegationTest is DevTestSetup { vm.stopPrank(); } - function testOwnerCanSetInterestBelowMin() public { - uint256 troveId = openTroveAndSetIndividualDelegate(); - - vm.startPrank(A); - borrowerOperations.adjustTroveInterestRate(troveId, MIN_ANNUAL_INTEREST_RATE, 0, 0, 1e24); - vm.stopPrank(); - } - - function testOwnerCanSetInterestAboveMax() public { - uint256 troveId = openTroveAndSetIndividualDelegate(); - - vm.startPrank(A); - borrowerOperations.adjustTroveInterestRate(troveId, 50e16, 0, 0, 1e24); - vm.stopPrank(); - } - function testSetDelegateRevertsIfTroveIsClosed() public { vm.startPrank(B); borrowerOperations.registerBatchManager(1e16, 20e16, 5e16, 25e14, MIN_INTEREST_RATE_CHANGE_PERIOD); @@ -137,17 +121,17 @@ contract InterestIndividualDelegationTest is DevTestSetup { vm.stopPrank(); } - function testSetDelegateRevertsIfTroveIsZombie() public { + function testSetDelegateRevertsIfTroveIsUnredeemable() public { vm.startPrank(B); borrowerOperations.registerBatchManager(1e16, 20e16, 5e16, 25e14, MIN_INTEREST_RATE_CHANGE_PERIOD); vm.stopPrank(); // Open trove uint256 troveId = openTroveNoHints100pct(A, 100e18, 5000e18, 5e16); - // Make trove zombie + // Make trove unredeemable redeem(A, 4000e18); - // Check A’s trove is zombie - assertEq(troveManager.checkTroveIsZombie(troveId), true, "A trove should be zombie"); + // Check A’s trove is unredeemable + assertEq(troveManager.checkTroveIsUnredeemable(troveId), true, "A trove should be unredeemable"); // Set batch manager (B) vm.startPrank(A); diff --git a/contracts/src/test/redemptions.t.sol b/contracts/src/test/redemptions.t.sol index 85c8b2cc..ebf93e7e 100644 --- a/contracts/src/test/redemptions.t.sol +++ b/contracts/src/test/redemptions.t.sol @@ -22,14 +22,12 @@ contract Redemptions is DevTestSetup { uint256 debt_A = troveManager.getTroveEntireDebt(troveIDs.A); uint256 debt_B = troveManager.getTroveEntireDebt(troveIDs.B); - /* console.log(troveIDs.A, "A id"); console.log(troveIDs.B, "B id"); console.log(sortedTroves.contains(troveIDs.B), "B is in list t0"); console.log(troveManager.getTroveEntireDebt(troveIDs.B), "A debt t0"); console.log(troveManager.getTroveEntireDebt(troveIDs.B), "B debt t0"); console.log(sortedTroves.getLast(), "first to redeem t0"); - */ uint256 debt_C = troveManager.getTroveEntireDebt(troveIDs.C); uint256 debt_D = troveManager.getTroveEntireDebt(troveIDs.D); @@ -75,8 +73,8 @@ contract Redemptions is DevTestSetup { redeem(E, redeemAmount_1); // Check A and B still open - assertEq(uint8(troveManager.getTroveStatus(troveIDs.A)), uint8(ITroveManager.Status.zombie)); - assertEq(uint8(troveManager.getTroveStatus(troveIDs.B)), uint8(ITroveManager.Status.zombie)); + assertEq(uint8(troveManager.getTroveStatus(troveIDs.A)), uint8(ITroveManager.Status.unredeemable)); + assertEq(uint8(troveManager.getTroveStatus(troveIDs.B)), uint8(ITroveManager.Status.unredeemable)); } function testFullRedemptionLeavesTrovesWithDebtEqualToZero() public { @@ -114,8 +112,8 @@ contract Redemptions is DevTestSetup { redeem(E, redeemAmount_2); // Check A and B still open with debt == zero - assertEq(uint8(troveManager.getTroveStatus(troveIDs.A)), uint8(ITroveManager.Status.zombie)); - assertEq(uint8(troveManager.getTroveStatus(troveIDs.B)), uint8(ITroveManager.Status.zombie)); + assertEq(uint8(troveManager.getTroveStatus(troveIDs.A)), uint8(ITroveManager.Status.unredeemable)); + assertEq(uint8(troveManager.getTroveStatus(troveIDs.B)), uint8(ITroveManager.Status.unredeemable)); assertEq(troveManager.getTroveEntireDebt(troveIDs.A), 0); assertEq(troveManager.getTroveEntireDebt(troveIDs.B), 0); @@ -281,8 +279,7 @@ contract Redemptions is DevTestSetup { _redeemAndCreateZombieTrovesAAndB(troveIDs); - assertEq(uint8(troveManager.getTroveStatus(troveIDs.A)), uint8(ITroveManager.Status.zombie)); - assertEq(troveManager.lastZombieTroveId(), troveIDs.B, "Wrong last zombie trove pointer"); + assertEq(uint8(troveManager.getTroveStatus(troveIDs.A)), uint8(ITroveManager.Status.unredeemable)); } function testTroveRedeemedToBelowMIN_DEBTBecomesZombieTrove() public { @@ -290,8 +287,7 @@ contract Redemptions is DevTestSetup { _redeemAndCreateZombieTrovesAAndB(troveIDs); - assertEq(uint8(troveManager.getTroveStatus(troveIDs.B)), uint8(ITroveManager.Status.zombie)); - assertEq(troveManager.lastZombieTroveId(), troveIDs.B, "Wrong last zombie trove pointer"); + assertEq(uint8(troveManager.getTroveStatus(troveIDs.B)), uint8(ITroveManager.Status.unredeemable)); } function testTroveRedeemedToAboveMIN_DEBTDoesNotBecomesZombieTrove() public { @@ -300,7 +296,6 @@ contract Redemptions is DevTestSetup { _redeemAndCreateZombieTroveAAndHitB(troveIDs); assertEq(uint8(troveManager.getTroveStatus(troveIDs.C)), uint8(ITroveManager.Status.active)); - assertEq(troveManager.lastZombieTroveId(), 0, "Wrong last zombie trove pointer"); } function testZombieTrovesRemovedFromSortedList() public { @@ -322,12 +317,9 @@ contract Redemptions is DevTestSetup { // Check Trove with lowest interest rate is C assertEq(sortedTroves.getLast(), troveIDs.C); - - // Check last Zombie trove pointer - assertEq(troveManager.lastZombieTroveId(), troveIDs.B, "Wrong last zombie trove pointer"); } - function testZombieTroveCanStillBeRedeemedFrom() public { + function testZombieTroveCantBeRedeemedFrom() public { (,, ABCDEF memory troveIDs) = _setupForRedemptionAscendingInterest(); _redeemAndCreateZombieTrovesAAndB(troveIDs); @@ -339,154 +331,14 @@ contract Redemptions is DevTestSetup { uint256 redeemAmount = debt_B / 2; redeem(E, redeemAmount); - // Check B's debt changed from redeemAmount < debt_B; - assertEq(troveManager.getTroveEntireDebt(troveIDs.B), debt_B - redeemAmount); + // Check B's debt unchanged from redeemAmount < debt_B; + assertEq(debt_B, troveManager.getTroveEntireDebt(troveIDs.B)); - debt_B = troveManager.getTroveEntireDebt(troveIDs.B); redeemAmount = debt_B + 1; redeem(E, redeemAmount); - // Check B's debt changed from redeemAmount > debt_B; - assertEq(troveManager.getTroveEntireDebt(troveIDs.B), 0); - } - - function testRedemptionsWithNoPartialLeaveNoPointerToZombieTroves() public { - (,, ABCDEF memory troveIDs) = _setupForRedemptionAscendingInterest(); - - _redeemAndCreateEmptyZombieTrovesAAndB(troveIDs); - - // Check A, B removed from sorted list - assertFalse(sortedTroves.contains(troveIDs.A)); - assertFalse(sortedTroves.contains(troveIDs.B)); - - // Check A, B zombie (already checked in helper above) - //assertEq(uint8(troveManager.getTroveStatus(troveIDs.A)), uint8(ITroveManager.Status.zombie)); - //assertEq(uint8(troveManager.getTroveStatus(troveIDs.B)), uint8(ITroveManager.Status.zombie)); - - // Check A, B empty (already checked in helper above) - //assertEq(troveManager.getTroveEntireDebt(troveIDs.A), 0); - //assertEq(troveManager.getTroveEntireDebt(troveIDs.B), 0); - - // Check last Zombie trove pointer - assertEq(troveManager.lastZombieTroveId(), 0, "Wrong last zombie trove pointer"); - } - - function testZombieTrovePointerGetsResetIfLastOneIsFullyRedemeed() public { - (,, ABCDEF memory troveIDs) = _setupForRedemptionAscendingInterest(); - - _redeemAndCreateZombieTrovesAAndB(troveIDs); - - // Check last Zombie trove pointer - assertEq(troveManager.lastZombieTroveId(), troveIDs.B, "Wrong last zombie trove pointer before"); - - // Get B debt before 2nd redeem - uint256 debt_B = troveManager.getTroveEntireDebt(troveIDs.B); - assertGt(debt_B, 0, "B debt should be non zero"); - - uint256 redeemAmount = debt_B; - console2.log("redeem again"); - console2.log(redeemAmount, "redeemAmount"); - redeem(E, redeemAmount); - - // Check B is empty now - assertEq(troveManager.getTroveEntireDebt(troveIDs.B), 0, "B debt should be zero"); - - // Check last Zombie trove pointer - assertEq(troveManager.lastZombieTroveId(), 0, "Wrong last zombie trove pointer after"); - } - - function testZombieTrovePointerGetsResetIfTroveIsResuscitatedManuallyByOwner() public { - (,, ABCDEF memory troveIDs) = _setupForRedemptionAscendingInterest(); - - _redeemAndCreateZombieTrovesAAndB(troveIDs); - - // Check last Zombie trove pointer - assertEq(troveManager.lastZombieTroveId(), troveIDs.B, "Wrong last zombie trove pointer before"); - - // Restore trove - adjustZombieTrove(B, troveIDs.B, 0, false, MIN_DEBT, true); - - // Check B is above min debt - assertGt(troveManager.getTroveEntireDebt(troveIDs.B), MIN_DEBT, "B debt should be above min"); - - // Check last Zombie trove pointer - assertEq(troveManager.lastZombieTroveId(), 0, "Wrong last zombie trove pointer after"); - } - - function testZombieTrovePointerGetsResetIfTroveIsResuscitatedViaInterest() public { - (,, ABCDEF memory troveIDs) = _setupForRedemptionAscendingInterest(); - - _redeemAndCreateZombieTrovesAAndB(troveIDs); - - // Check last Zombie trove pointer - assertEq(troveManager.lastZombieTroveId(), troveIDs.B, "Wrong last zombie trove pointer before"); - - // Restore trove - adjustZombieTrove(B, troveIDs.B, 0, false, MIN_DEBT, true); - // fast-forward time a lot - vm.warp(block.timestamp + 3650 days); - - // E applies interest on B's Trove - applyPendingDebt(E, troveIDs.B); - - // Check B is above min debt - assertGt(troveManager.getTroveEntireDebt(troveIDs.B), MIN_DEBT, "B debt should be above min"); - - // Check last Zombie trove pointer - assertEq(troveManager.lastZombieTroveId(), 0, "Wrong last zombie trove pointer after"); - } - - function testZombieTrovePointerGetsResetIfTroveIsClosed() public { - (,, ABCDEF memory troveIDs) = _setupForRedemptionAscendingInterest(); - - _redeemAndCreateZombieTrovesAAndB(troveIDs); - - // Check last Zombie trove pointer - assertEq(troveManager.lastZombieTroveId(), troveIDs.B, "Wrong last zombie trove pointer before"); - - // Get B debt before 2nd redeem - uint256 debt_B = troveManager.getTroveEntireDebt(troveIDs.B); - assertGt(debt_B, 0, "B debt should be non zero"); - - deal(address(boldToken), B, debt_B); - closeTrove(B, troveIDs.B); - - // Check B is closed - assertEq( - uint8(troveManager.getTroveStatus(troveIDs.B)), - uint8(ITroveManager.Status.closedByOwner), - "B trove should be closed" - ); - - // Check last Zombie trove pointer - assertEq(troveManager.lastZombieTroveId(), 0, "Wrong last zombie trove pointer after"); - } - - function testZombieTrovePointerGetsResetIfTroveIsLiquidated() public { - (,, ABCDEF memory troveIDs) = _setupForRedemptionAscendingInterest(); - - _redeemAndCreateZombieTrovesAAndB(troveIDs); - - // Check last Zombie trove pointer - assertEq(troveManager.lastZombieTroveId(), troveIDs.B, "Wrong last zombie trove pointer before"); - - // Liquidate B - console2.log( - troveManager.getCurrentICR(troveIDs.B, priceFeed.getPrice()), - "troveManager.getCurrentICR(troveIDs.E, price)" - ); - priceFeed.setPrice(priceFeed.getPrice() / 25); - liquidate(A, troveIDs.B); - - // Check B is liquidated - assertEq( - uint8(troveManager.getTroveStatus(troveIDs.B)), - uint8(ITroveManager.Status.closedByLiquidation), - "B trove should be liquidated" - ); - - // Check last Zombie trove pointer - assertEq(troveManager.lastZombieTroveId(), 0, "Wrong last zombie trove pointer after"); + // Check B's debt unchanged from redeemAmount > debt_B; + assertEq(debt_B, troveManager.getTroveEntireDebt(troveIDs.B)); } function testZombieTrovesCanReceiveRedistGains() public { @@ -617,8 +469,8 @@ contract Redemptions is DevTestSetup { transferBold(E, A, boldToken.balanceOf(E) / 2); transferBold(E, B, boldToken.balanceOf(E)); - assertEq(uint8(troveManager.getTroveStatus(troveIDs.A)), uint8(ITroveManager.Status.zombie)); - assertEq(uint8(troveManager.getTroveStatus(troveIDs.B)), uint8(ITroveManager.Status.zombie)); + assertEq(uint8(troveManager.getTroveStatus(troveIDs.A)), uint8(ITroveManager.Status.unredeemable)); + assertEq(uint8(troveManager.getTroveStatus(troveIDs.B)), uint8(ITroveManager.Status.unredeemable)); closeTrove(A, troveIDs.A); closeTrove(B, troveIDs.B); @@ -644,8 +496,8 @@ contract Redemptions is DevTestSetup { uint256 surplusDebt = 37; // A and B withdraw Bold from their zombie Trove - adjustZombieTrove(A, troveIDs.A, 0, false, debtDelta_A + surplusDebt, true); - adjustZombieTrove(B, troveIDs.B, 0, false, debtDelta_A + surplusDebt, true); + adjustUnredeemableTrove(A, troveIDs.A, 0, false, debtDelta_A + surplusDebt, true); + adjustUnredeemableTrove(B, troveIDs.B, 0, false, debtDelta_A + surplusDebt, true); // Check they are above the min debt assertGt(troveManager.getTroveEntireDebt(troveIDs.A), MIN_DEBT); @@ -669,8 +521,8 @@ contract Redemptions is DevTestSetup { uint256 surplusDebt = 37; // A and B withdraw Bold from their zombie Trove - adjustZombieTrove(A, troveIDs.A, 0, false, debtDelta_A + surplusDebt, true); - adjustZombieTrove(B, troveIDs.B, 0, false, debtDelta_A + surplusDebt, true); + adjustUnredeemableTrove(A, troveIDs.A, 0, false, debtDelta_A + surplusDebt, true); + adjustUnredeemableTrove(B, troveIDs.B, 0, false, debtDelta_A + surplusDebt, true); // Check they are above the min debt assertGt(troveManager.getTroveEntireDebt(troveIDs.A), MIN_DEBT); @@ -702,8 +554,8 @@ contract Redemptions is DevTestSetup { assertFalse(sortedTroves.contains(troveIDs.B)); // A and B withdraw Bold from their zombie Trove - adjustZombieTrove(A, troveIDs.A, 0, false, debtDelta_A + surplusDebt, true); - adjustZombieTrove(B, troveIDs.B, 0, false, debtDelta_A + surplusDebt, true); + adjustUnredeemableTrove(A, troveIDs.A, 0, false, debtDelta_A + surplusDebt, true); + adjustUnredeemableTrove(B, troveIDs.B, 0, false, debtDelta_A + surplusDebt, true); // Check they are above the min debt assertGt(troveManager.getTroveEntireDebt(troveIDs.A), MIN_DEBT); @@ -734,8 +586,8 @@ contract Redemptions is DevTestSetup { uint256 surplusDebt = 37; // A and B withdraw Bold from their zombie Trove - adjustZombieTrove(A, troveIDs.A, 0, false, debtDelta_A + surplusDebt, true); - adjustZombieTrove(B, troveIDs.B, 0, false, debtDelta_A + surplusDebt, true); + adjustUnredeemableTrove(A, troveIDs.A, 0, false, debtDelta_A + surplusDebt, true); + adjustUnredeemableTrove(B, troveIDs.B, 0, false, debtDelta_A + surplusDebt, true); // Check they are above the min debt assertGt(troveManager.getTroveEntireDebt(troveIDs.A), MIN_DEBT, "A debt should be above min"); @@ -759,10 +611,10 @@ contract Redemptions is DevTestSetup { // A and B attempt to withdraw Bold, but not enough vm.expectRevert(BorrowerOperations.DebtBelowMin.selector); - this.adjustZombieTrove(A, troveIDs.A, 0, false, borrow_A, true); + this.adjustUnredeemableTrove(A, troveIDs.A, 0, false, borrow_A, true); vm.expectRevert(BorrowerOperations.DebtBelowMin.selector); - this.adjustZombieTrove(B, troveIDs.B, 0, false, borrow_B, true); + this.adjustUnredeemableTrove(B, troveIDs.B, 0, false, borrow_B, true); } function testZombieTroveBorrowerCanNotRepayDebt() public { @@ -871,9 +723,9 @@ contract Redemptions is DevTestSetup { assertEq(troveManager.calcTroveAccruedInterest(troveIDs.A), 0); assertGt(troveManager.calcTroveAccruedInterest(troveIDs.B), 0); // Troves are zombie - assertTrue(troveManager.checkTroveIsZombie(troveIDs.A)); + assertTrue(troveManager.checkTroveIsUnredeemable(troveIDs.A)); assertFalse(sortedTroves.contains(troveIDs.A)); - assertTrue(troveManager.checkTroveIsZombie(troveIDs.B)); + assertTrue(troveManager.checkTroveIsUnredeemable(troveIDs.B)); assertFalse(sortedTroves.contains(troveIDs.B)); // E applies interest on A and B's Troves @@ -884,9 +736,9 @@ contract Redemptions is DevTestSetup { assertEq(troveManager.calcTroveAccruedInterest(troveIDs.B), 0); // Troves are still zombie - assertTrue(troveManager.checkTroveIsZombie(troveIDs.A)); + assertTrue(troveManager.checkTroveIsUnredeemable(troveIDs.A)); assertFalse(sortedTroves.contains(troveIDs.A)); - assertTrue(troveManager.checkTroveIsZombie(troveIDs.B)); + assertTrue(troveManager.checkTroveIsUnredeemable(troveIDs.B)); assertFalse(sortedTroves.contains(troveIDs.B)); } @@ -901,9 +753,9 @@ contract Redemptions is DevTestSetup { assertEq(troveManager.calcTroveAccruedInterest(troveIDs.A), 0); assertGt(troveManager.calcTroveAccruedInterest(troveIDs.B), 0); // Troves are zombie - assertTrue(troveManager.checkTroveIsZombie(troveIDs.A)); + assertTrue(troveManager.checkTroveIsUnredeemable(troveIDs.A)); assertFalse(sortedTroves.contains(troveIDs.A)); - assertTrue(troveManager.checkTroveIsZombie(troveIDs.B)); + assertTrue(troveManager.checkTroveIsUnredeemable(troveIDs.B)); assertFalse(sortedTroves.contains(troveIDs.B)); // E applies interest on A and B's Troves @@ -913,9 +765,9 @@ contract Redemptions is DevTestSetup { assertEq(troveManager.calcTroveAccruedInterest(troveIDs.A), 0); assertEq(troveManager.calcTroveAccruedInterest(troveIDs.B), 0); // Troves B is not zombie anymore (A still is) - assertTrue(troveManager.checkTroveIsZombie(troveIDs.A)); + assertTrue(troveManager.checkTroveIsUnredeemable(troveIDs.A)); assertFalse(sortedTroves.contains(troveIDs.A)); - assertFalse(troveManager.checkTroveIsZombie(troveIDs.B)); + assertFalse(troveManager.checkTroveIsUnredeemable(troveIDs.B)); assertTrue(sortedTroves.contains(troveIDs.B)); } @@ -939,7 +791,7 @@ contract Redemptions is DevTestSetup { // assertFalse(troveManager.checkBelowCriticalThreshold(price)); assertLt(troveManager.getCurrentICR(troveIDs.B, price), MCR); - assertEq(uint8(troveManager.getTroveStatus(troveIDs.B)), uint8(ITroveManager.Status.zombie)); + assertEq(uint8(troveManager.getTroveStatus(troveIDs.B)), uint8(ITroveManager.Status.unredeemable)); // E liquidates B liquidate(E, troveIDs.B); diff --git a/contracts/src/test/shutdown.t.sol b/contracts/src/test/shutdown.t.sol index 1f7e677b..540297b9 100644 --- a/contracts/src/test/shutdown.t.sol +++ b/contracts/src/test/shutdown.t.sol @@ -219,11 +219,11 @@ contract ShutdownTest is DevTestSetup { vm.stopPrank(); } - function testCannotAdjustZombieTroveAfterShutdown() public { + function testCannotAdjustUnredeemableTroveAfterShutdown() public { uint256 troveId = openMulticollateralTroveNoHints100pctWithIndex(0, A, 0, 11e18, 10000e18, 5e16); openMulticollateralTroveNoHints100pctWithIndex(0, B, 0, 22e18, 20000e18, 6e16); - // B redeems from A’s trove, to make it zombie + // B redeems from A’s trove, to make it unredeemable //deal(address(boldToken), B, 20000e18); vm.startPrank(B); collateralRegistry.redeemCollateral(10000e18, 0, 1e18); @@ -234,12 +234,12 @@ contract ShutdownTest is DevTestSetup { contractsArray[0].priceFeed.setPrice(500e18); contractsArray[0].borrowerOperations.shutdown(); - // Check A’s trove is zombie - assertEq(troveManager.checkTroveIsZombie(troveId), true, "A trove should be zombie"); + // Check A’s trove is unredeemable + assertEq(troveManager.checkTroveIsUnredeemable(troveId), true, "A trove should be unredeemable"); vm.startPrank(A); vm.expectRevert(BorrowerOperations.IsShutDown.selector); - borrowerOperations.adjustZombieTrove(troveId, 1e18, true, 0, false, 0, 0, 1000e18); + borrowerOperations.adjustUnredeemableTrove(troveId, 1e18, true, 0, false, 0, 0, 1000e18); vm.stopPrank(); } diff --git a/contracts/src/test/troveNFT.t.sol b/contracts/src/test/troveNFT.t.sol index 9079e7c6..3059a039 100644 --- a/contracts/src/test/troveNFT.t.sol +++ b/contracts/src/test/troveNFT.t.sol @@ -33,33 +33,4 @@ contract troveNFTTest is DevTestSetup { emit log_string(uri); } - - function testTroveURIAttributes() public { - uint256 troveId = _openTrove(); - - TroveNFT troveNFT = TroveNFT(address(troveManager.troveNFT())); - - string memory uri = troveNFT.tokenURI(troveId); - - emit log_string(uri); - - /** - * TODO: validate each individual attribute, or manually make a json and validate it all at once - * // Check for expected attributes - * assertTrue(LibString.contains(uri, '"trait_type": "Collateral Token"'), "Collateral Token attribute missing"); - * assertTrue(LibString.contains(uri, '"trait_type": "Collateral Amount"'), "Collateral Amount attribute missing"); - * assertTrue(LibString.contains(uri, '"trait_type": "Debt Token"'), "Debt Token attribute missing"); - * assertTrue(LibString.contains(uri, '"trait_type": "Debt Amount"'), "Debt Amount attribute missing"); - * assertTrue(LibString.contains(uri, '"trait_type": "Interest Rate"'), "Interest Rate attribute missing"); - * assertTrue(LibString.contains(uri, '"trait_type": "Status"'), "Status attribute missing"); - * - * // Check for expected values - * //assertTrue(LibString.contains(uri, string.concat('"value": "', Strings.toHexString(address(collateral)))), "Incorrect Collateral Token value"); - * assertTrue(LibString.contains(uri, '"value": "2000000000000000000"'), "Incorrect Collateral Amount value"); - * assertTrue(LibString.contains(uri, string.concat('"value": "', Strings.toHexString(address(boldToken)))), "Incorrect Debt Token value"); - * assertTrue(LibString.contains(uri, '"value": "1000000000000000000000"'), "Incorrect Debt Amount value"); - * assertTrue(LibString.contains(uri, '"value": "5000000000000000"'), "Incorrect Interest Rate value"); - * assertTrue(LibString.contains(uri, '"value": "Active"'), "Incorrect Status value"); - */ - } } diff --git a/contracts/src/test/zapperGasComp.t.sol b/contracts/src/test/zapperGasComp.t.sol index 9db79bda..1a21afb7 100644 --- a/contracts/src/test/zapperGasComp.t.sol +++ b/contracts/src/test/zapperGasComp.t.sol @@ -307,7 +307,7 @@ contract ZapperGasCompTest is DevTestSetup { } // TODO: more adjustment combinations - function testCanAdjustZombieTroveWithdrawCollAndBold() external { + function testCanAdjustUnredeemableTroveWithdrawCollAndBold() external { uint256 collAmount1 = 10 ether; uint256 collAmount2 = 1 ether; uint256 boldAmount1 = 10000e18; @@ -335,7 +335,7 @@ contract ZapperGasCompTest is DevTestSetup { gasCompZapper.setRemoveManagerWithReceiver(troveId, B, A); vm.stopPrank(); - // Redeem to make trove zombie + // Redeem to make trove unredeemable vm.startPrank(A); collateralRegistry.redeemCollateral(boldAmount1 - boldAmount2, 10, 1e18); vm.stopPrank(); @@ -347,7 +347,9 @@ contract ZapperGasCompTest is DevTestSetup { // Adjust (withdraw coll and Bold) vm.startPrank(B); - gasCompZapper.adjustZombieTroveWithRawETH(troveId, collAmount2, false, boldAmount2, true, 0, 0, boldAmount2); + gasCompZapper.adjustUnredeemableTroveWithRawETH( + troveId, collAmount2, false, boldAmount2, true, 0, 0, boldAmount2 + ); vm.stopPrank(); assertEq(troveManager.getTroveEntireColl(troveId), troveCollBefore - collAmount2, "Trove coll mismatch"); diff --git a/contracts/src/test/zapperWETH.t.sol b/contracts/src/test/zapperWETH.t.sol index 2d5bb28c..78df9d3d 100644 --- a/contracts/src/test/zapperWETH.t.sol +++ b/contracts/src/test/zapperWETH.t.sol @@ -342,7 +342,7 @@ contract ZapperWETHTest is DevTestSetup { } // TODO: more adjustment combinations - function testCanAdjustZombieTroveWithdrawCollAndBold() external { + function testCanAdjustUnredeemableTroveWithdrawCollAndBold() external { uint256 ethAmount1 = 10 ether; uint256 ethAmount2 = 1 ether; uint256 boldAmount1 = 10000e18; @@ -369,7 +369,7 @@ contract ZapperWETHTest is DevTestSetup { wethZapper.setRemoveManagerWithReceiver(troveId, B, A); vm.stopPrank(); - // Redeem to make trove zombie + // Redeem to make trove unredeemable vm.startPrank(A); collateralRegistry.redeemCollateral(boldAmount1 - boldAmount2, 10, 1e18); vm.stopPrank(); @@ -381,7 +381,7 @@ contract ZapperWETHTest is DevTestSetup { // Adjust (withdraw coll and Bold) vm.startPrank(B); - wethZapper.adjustZombieTroveWithRawETH(troveId, ethAmount2, false, boldAmount2, true, 0, 0, boldAmount2); + wethZapper.adjustUnredeemableTroveWithRawETH(troveId, ethAmount2, false, boldAmount2, true, 0, 0, boldAmount2); vm.stopPrank(); assertEq(troveManager.getTroveEntireColl(troveId), troveCollBefore - ethAmount2, "Trove coll mismatch"); diff --git a/frontend/app/.env b/frontend/app/.env index 5456b7c8..e455d9ae 100644 --- a/frontend/app/.env +++ b/frontend/app/.env @@ -26,6 +26,9 @@ NEXT_PUBLIC_CHAIN_RPC_URL=http://127.0.0.1:8545 # NEXT_PUBLIC_CHAIN_BLOCK_EXPLORER=Liquity Testnet|https://testnet.liquity.org/ # NEXT_PUBLIC_CHAIN_CONTRACT_MULTICALL=0xffB2BAa708261533b51D18394fd8AFd0E32aBC55|488 +NEXT_PUBLIC_LQTY_TOKEN=0x6DEA81C8171D0bA574754EF6F8b412F2Ed88c54D +NEXT_PUBLIC_LUSD_TOKEN=0x5f98805A4E8be255a32880FDeC7F6728C6568bA0 + # Dev & testnet collaterals NEXT_PUBLIC_COLL_0_TOKEN_ID=ETH NEXT_PUBLIC_COLL_1_TOKEN_ID=STETH diff --git a/frontend/app/.graphclient/index.ts b/frontend/app/.graphclient/index.ts index 87fe6975..cc577175 100644 --- a/frontend/app/.graphclient/index.ts +++ b/frontend/app/.graphclient/index.ts @@ -62,8 +62,49 @@ export type Block_height = { readonly number_gte?: InputMaybe; }; +export type BorrowerInfo = { + readonly id: Scalars['ID']['output']; + readonly troves: Scalars['Int']['output']; + readonly trovesByCollateral: ReadonlyArray; +}; + +export type BorrowerInfo_filter = { + readonly id?: InputMaybe; + readonly id_not?: InputMaybe; + readonly id_gt?: InputMaybe; + readonly id_lt?: InputMaybe; + readonly id_gte?: InputMaybe; + readonly id_lte?: InputMaybe; + readonly id_in?: InputMaybe>; + readonly id_not_in?: InputMaybe>; + readonly troves?: InputMaybe; + readonly troves_not?: InputMaybe; + readonly troves_gt?: InputMaybe; + readonly troves_lt?: InputMaybe; + readonly troves_gte?: InputMaybe; + readonly troves_lte?: InputMaybe; + readonly troves_in?: InputMaybe>; + readonly troves_not_in?: InputMaybe>; + readonly trovesByCollateral?: InputMaybe>; + readonly trovesByCollateral_not?: InputMaybe>; + readonly trovesByCollateral_contains?: InputMaybe>; + readonly trovesByCollateral_contains_nocase?: InputMaybe>; + readonly trovesByCollateral_not_contains?: InputMaybe>; + readonly trovesByCollateral_not_contains_nocase?: InputMaybe>; + /** Filter for the block changed event. */ + readonly _change_block?: InputMaybe; + readonly and?: InputMaybe>>; + readonly or?: InputMaybe>>; +}; + +export type BorrowerInfo_orderBy = + | 'id' + | 'troves' + | 'trovesByCollateral'; + export type Collateral = { readonly id: Scalars['ID']['output']; + readonly collIndex: Scalars['Int']['output']; readonly token: Token; readonly minCollRatio: Scalars['BigInt']['output']; readonly troves: ReadonlyArray; @@ -193,6 +234,7 @@ export type CollateralAddresses_orderBy = | 'borrowerOperations' | 'collateral' | 'collateral__id' + | 'collateral__collIndex' | 'collateral__minCollRatio' | 'collateral__totalDeposited' | 'collateral__totalDebt' @@ -211,6 +253,14 @@ export type Collateral_filter = { readonly id_lte?: InputMaybe; readonly id_in?: InputMaybe>; readonly id_not_in?: InputMaybe>; + readonly collIndex?: InputMaybe; + readonly collIndex_not?: InputMaybe; + readonly collIndex_gt?: InputMaybe; + readonly collIndex_lt?: InputMaybe; + readonly collIndex_gte?: InputMaybe; + readonly collIndex_lte?: InputMaybe; + readonly collIndex_in?: InputMaybe>; + readonly collIndex_not_in?: InputMaybe>; readonly token?: InputMaybe; readonly token_not?: InputMaybe; readonly token_gt?: InputMaybe; @@ -266,6 +316,7 @@ export type Collateral_filter = { export type Collateral_orderBy = | 'id' + | 'collIndex' | 'token' | 'token__id' | 'token__name' @@ -352,6 +403,8 @@ export type Query = { readonly interestRateBrackets: ReadonlyArray; readonly trove?: Maybe; readonly troves: ReadonlyArray; + readonly borrowerInfo?: Maybe; + readonly borrowerInfos: ReadonlyArray; /** Access to subgraph metadata */ readonly _meta?: Maybe<_Meta_>; }; @@ -447,6 +500,24 @@ export type QuerytrovesArgs = { }; +export type QueryborrowerInfoArgs = { + id: Scalars['ID']['input']; + block?: InputMaybe; + subgraphError?: _SubgraphErrorPolicy_; +}; + + +export type QueryborrowerInfosArgs = { + skip?: InputMaybe; + first?: InputMaybe; + orderBy?: InputMaybe; + orderDirection?: InputMaybe; + where?: InputMaybe; + block?: InputMaybe; + subgraphError?: _SubgraphErrorPolicy_; +}; + + export type Query_metaArgs = { block?: InputMaybe; }; @@ -462,6 +533,8 @@ export type Subscription = { readonly interestRateBrackets: ReadonlyArray; readonly trove?: Maybe; readonly troves: ReadonlyArray; + readonly borrowerInfo?: Maybe; + readonly borrowerInfos: ReadonlyArray; /** Access to subgraph metadata */ readonly _meta?: Maybe<_Meta_>; }; @@ -557,6 +630,24 @@ export type SubscriptiontrovesArgs = { }; +export type SubscriptionborrowerInfoArgs = { + id: Scalars['ID']['input']; + block?: InputMaybe; + subgraphError?: _SubgraphErrorPolicy_; +}; + + +export type SubscriptionborrowerInfosArgs = { + skip?: InputMaybe; + first?: InputMaybe; + orderBy?: InputMaybe; + orderDirection?: InputMaybe; + where?: InputMaybe; + block?: InputMaybe; + subgraphError?: _SubgraphErrorPolicy_; +}; + + export type Subscription_metaArgs = { block?: InputMaybe; }; @@ -657,6 +748,7 @@ export type Token_orderBy = | 'id' | 'collateral' | 'collateral__id' + | 'collateral__collIndex' | 'collateral__minCollRatio' | 'collateral__totalDeposited' | 'collateral__totalDebt' @@ -666,6 +758,7 @@ export type Token_orderBy = export type Trove = { readonly id: Scalars['ID']['output']; + readonly troveId: Scalars['String']['output']; readonly borrower: Scalars['Bytes']['output']; readonly debt: Scalars['BigInt']['output']; readonly deposit: Scalars['BigInt']['output']; @@ -685,6 +778,26 @@ export type Trove_filter = { readonly id_lte?: InputMaybe; readonly id_in?: InputMaybe>; readonly id_not_in?: InputMaybe>; + readonly troveId?: InputMaybe; + readonly troveId_not?: InputMaybe; + readonly troveId_gt?: InputMaybe; + readonly troveId_lt?: InputMaybe; + readonly troveId_gte?: InputMaybe; + readonly troveId_lte?: InputMaybe; + readonly troveId_in?: InputMaybe>; + readonly troveId_not_in?: InputMaybe>; + readonly troveId_contains?: InputMaybe; + readonly troveId_contains_nocase?: InputMaybe; + readonly troveId_not_contains?: InputMaybe; + readonly troveId_not_contains_nocase?: InputMaybe; + readonly troveId_starts_with?: InputMaybe; + readonly troveId_starts_with_nocase?: InputMaybe; + readonly troveId_not_starts_with?: InputMaybe; + readonly troveId_not_starts_with_nocase?: InputMaybe; + readonly troveId_ends_with?: InputMaybe; + readonly troveId_ends_with_nocase?: InputMaybe; + readonly troveId_not_ends_with?: InputMaybe; + readonly troveId_not_ends_with_nocase?: InputMaybe; readonly borrower?: InputMaybe; readonly borrower_not?: InputMaybe; readonly borrower_gt?: InputMaybe; @@ -772,6 +885,7 @@ export type Trove_filter = { export type Trove_orderBy = | 'id' + | 'troveId' | 'borrower' | 'debt' | 'deposit' @@ -781,6 +895,7 @@ export type Trove_orderBy = | 'closedAt' | 'collateral' | 'collateral__id' + | 'collateral__collIndex' | 'collateral__minCollRatio' | 'collateral__totalDeposited' | 'collateral__totalDebt'; @@ -910,6 +1025,9 @@ export type ResolversTypes = ResolversObject<{ BlockChangedFilter: BlockChangedFilter; Block_height: Block_height; Boolean: ResolverTypeWrapper; + BorrowerInfo: ResolverTypeWrapper; + BorrowerInfo_filter: BorrowerInfo_filter; + BorrowerInfo_orderBy: BorrowerInfo_orderBy; Bytes: ResolverTypeWrapper; Collateral: ResolverTypeWrapper; CollateralAddresses: ResolverTypeWrapper; @@ -947,6 +1065,8 @@ export type ResolversParentTypes = ResolversObject<{ BlockChangedFilter: BlockChangedFilter; Block_height: Block_height; Boolean: Scalars['Boolean']['output']; + BorrowerInfo: BorrowerInfo; + BorrowerInfo_filter: BorrowerInfo_filter; Bytes: Scalars['Bytes']['output']; Collateral: Collateral; CollateralAddresses: CollateralAddresses; @@ -994,12 +1114,20 @@ export interface BigIntScalarConfig extends GraphQLScalarTypeConfig = ResolversObject<{ + id?: Resolver; + troves?: Resolver; + trovesByCollateral?: Resolver, ParentType, ContextType>; + __isTypeOf?: IsTypeOfResolverFn; +}>; + export interface BytesScalarConfig extends GraphQLScalarTypeConfig { name: 'Bytes'; } export type CollateralResolvers = ResolversObject<{ id?: Resolver; + collIndex?: Resolver; token?: Resolver; minCollRatio?: Resolver; troves?: Resolver, ParentType, ContextType, RequireFields>; @@ -1044,6 +1172,8 @@ export type QueryResolvers, ParentType, ContextType, RequireFields>; trove?: Resolver, ParentType, ContextType, RequireFields>; troves?: Resolver, ParentType, ContextType, RequireFields>; + borrowerInfo?: Resolver, ParentType, ContextType, RequireFields>; + borrowerInfos?: Resolver, ParentType, ContextType, RequireFields>; _meta?: Resolver, ParentType, ContextType, Partial>; }>; @@ -1058,6 +1188,8 @@ export type SubscriptionResolvers, "interestRateBrackets", ParentType, ContextType, RequireFields>; trove?: SubscriptionResolver, "trove", ParentType, ContextType, RequireFields>; troves?: SubscriptionResolver, "troves", ParentType, ContextType, RequireFields>; + borrowerInfo?: SubscriptionResolver, "borrowerInfo", ParentType, ContextType, RequireFields>; + borrowerInfos?: SubscriptionResolver, "borrowerInfos", ParentType, ContextType, RequireFields>; _meta?: SubscriptionResolver, "_meta", ParentType, ContextType, Partial>; }>; @@ -1076,6 +1208,7 @@ export type TokenResolvers = ResolversObject<{ id?: Resolver; + troveId?: Resolver; borrower?: Resolver; debt?: Resolver; deposit?: Resolver; @@ -1105,6 +1238,7 @@ export type _Meta_Resolvers = ResolversObject<{ BigDecimal?: GraphQLScalarType; BigInt?: GraphQLScalarType; + BorrowerInfo?: BorrowerInfoResolvers; Bytes?: GraphQLScalarType; Collateral?: CollateralResolvers; CollateralAddresses?: CollateralAddressesResolvers; @@ -1171,7 +1305,7 @@ const liquity2Transforms = []; const additionalTypeDefs = [] as any[]; const liquity2Handler = new GraphqlHandler({ name: "liquity2", - config: {"endpoint":"http://localhost:8000/subgraphs/name/liquity2/liquity2"}, + config: {"endpoint":"https://api.studio.thegraph.com/query/42403/liquity2/version/latest"}, baseDir, cache, pubsub, @@ -1192,8 +1326,9 @@ const merger = new(BareMerger as any)({ store: rootStore.child('bareMerger') }) const documentHashMap = { - "45745732d955f1e9e56be85453b7766bb2b5d776bad265e1e6734958fbc111c8": TrovesByAccountDocument, -"45745732d955f1e9e56be85453b7766bb2b5d776bad265e1e6734958fbc111c8": TroveByIdDocument + "1117fda82156c6f9afe1ba1a1b37888d86ad9be723d9b2a14aeac6633ce20aad": TrovesByAccountDocument, +"1117fda82156c6f9afe1ba1a1b37888d86ad9be723d9b2a14aeac6633ce20aad": TrovesCountDocument, +"1117fda82156c6f9afe1ba1a1b37888d86ad9be723d9b2a14aeac6633ce20aad": TroveByIdDocument } additionalEnvelopPlugins.push(usePersistedOperations({ getPersistedOperation(key) { @@ -1220,14 +1355,21 @@ additionalEnvelopPlugins.push(usePersistedOperations({ return printWithCache(TrovesByAccountDocument); }, location: 'TrovesByAccountDocument.graphql', - sha256Hash: '45745732d955f1e9e56be85453b7766bb2b5d776bad265e1e6734958fbc111c8' + sha256Hash: '1117fda82156c6f9afe1ba1a1b37888d86ad9be723d9b2a14aeac6633ce20aad' + },{ + document: TrovesCountDocument, + get rawSDL() { + return printWithCache(TrovesCountDocument); + }, + location: 'TrovesCountDocument.graphql', + sha256Hash: '1117fda82156c6f9afe1ba1a1b37888d86ad9be723d9b2a14aeac6633ce20aad' },{ document: TroveByIdDocument, get rawSDL() { return printWithCache(TroveByIdDocument); }, location: 'TroveByIdDocument.graphql', - sha256Hash: '45745732d955f1e9e56be85453b7766bb2b5d776bad265e1e6734958fbc111c8' + sha256Hash: '1117fda82156c6f9afe1ba1a1b37888d86ad9be723d9b2a14aeac6633ce20aad' } ]; }, @@ -1288,22 +1430,29 @@ export type TrovesByAccountQueryVariables = Exact<{ export type TrovesByAccountQuery = { readonly troves: ReadonlyArray<( - Pick + Pick & { readonly collateral: ( - Pick + Pick & { readonly token: Pick } ) } )> }; +export type TrovesCountQueryVariables = Exact<{ + id: Scalars['ID']['input']; +}>; + + +export type TrovesCountQuery = { readonly borrowerInfo?: Maybe> }; + export type TroveByIdQueryVariables = Exact<{ id: Scalars['ID']['input']; }>; export type TroveByIdQuery = { readonly trove?: Maybe<( - Pick + Pick & { readonly collateral: ( - Pick + Pick & { readonly token: Pick } ) } )> }; @@ -1311,8 +1460,9 @@ export type TroveByIdQuery = { readonly trove?: Maybe<( export const TrovesByAccountDocument = gql` query TrovesByAccount($account: Bytes!) { - troves(where: {borrower: $account}) { + troves(where: {borrower: $account, closedAt: null}) { id + troveId borrower debt deposit @@ -1327,14 +1477,24 @@ export const TrovesByAccountDocument = gql` name } minCollRatio + collIndex } } } ` as unknown as DocumentNode; +export const TrovesCountDocument = gql` + query TrovesCount($id: ID!) { + borrowerInfo(id: $id) { + troves + trovesByCollateral + } +} + ` as unknown as DocumentNode; export const TroveByIdDocument = gql` query TroveById($id: ID!) { trove(id: $id) { id + troveId borrower debt deposit @@ -1349,6 +1509,7 @@ export const TroveByIdDocument = gql` name } minCollRatio + collIndex } } } @@ -1356,12 +1517,16 @@ export const TroveByIdDocument = gql` + export type Requester = (doc: DocumentNode, vars?: V, options?: C) => Promise | AsyncIterable export function getSdk(requester: Requester) { return { TrovesByAccount(variables: TrovesByAccountQueryVariables, options?: C): Promise { return requester(TrovesByAccountDocument, variables, options) as Promise; }, + TrovesCount(variables: TrovesCountQueryVariables, options?: C): Promise { + return requester(TrovesCountDocument, variables, options) as Promise; + }, TroveById(variables: TroveByIdQueryVariables, options?: C): Promise { return requester(TroveByIdDocument, variables, options) as Promise; } diff --git a/frontend/app/.graphclient/persisted_operations.json b/frontend/app/.graphclient/persisted_operations.json index 5c0346b7..e6d82218 100644 --- a/frontend/app/.graphclient/persisted_operations.json +++ b/frontend/app/.graphclient/persisted_operations.json @@ -1,3 +1,3 @@ { - "45745732d955f1e9e56be85453b7766bb2b5d776bad265e1e6734958fbc111c8": "query TrovesByAccount($account: Bytes!) {\n troves(where: {borrower: $account}) {\n id\n borrower\n debt\n deposit\n stake\n interestRate\n createdAt\n closedAt\n collateral {\n id\n token {\n symbol\n name\n }\n minCollRatio\n }\n }\n}\n\nquery TroveById($id: ID!) {\n trove(id: $id) {\n id\n borrower\n debt\n deposit\n stake\n interestRate\n createdAt\n closedAt\n collateral {\n id\n token {\n symbol\n name\n }\n minCollRatio\n }\n }\n}" + "1117fda82156c6f9afe1ba1a1b37888d86ad9be723d9b2a14aeac6633ce20aad": "query TrovesByAccount($account: Bytes!) {\n troves(where: {borrower: $account, closedAt: null}) {\n id\n troveId\n borrower\n debt\n deposit\n stake\n interestRate\n createdAt\n closedAt\n collateral {\n id\n token {\n symbol\n name\n }\n minCollRatio\n collIndex\n }\n }\n}\n\nquery TrovesCount($id: ID!) {\n borrowerInfo(id: $id) {\n troves\n trovesByCollateral\n }\n}\n\nquery TroveById($id: ID!) {\n trove(id: $id) {\n id\n troveId\n borrower\n debt\n deposit\n stake\n interestRate\n createdAt\n closedAt\n collateral {\n id\n token {\n symbol\n name\n }\n minCollRatio\n collIndex\n }\n }\n}" } \ No newline at end of file diff --git a/frontend/app/.graphclient/schema.graphql b/frontend/app/.graphclient/schema.graphql index d53c0294..c563e883 100644 --- a/frontend/app/.graphclient/schema.graphql +++ b/frontend/app/.graphclient/schema.graphql @@ -35,10 +35,52 @@ input Block_height { number_gte: Int } +type BorrowerInfo { + id: ID! + troves: Int! + trovesByCollateral: [Int!]! +} + +input BorrowerInfo_filter { + id: ID + id_not: ID + id_gt: ID + id_lt: ID + id_gte: ID + id_lte: ID + id_in: [ID!] + id_not_in: [ID!] + troves: Int + troves_not: Int + troves_gt: Int + troves_lt: Int + troves_gte: Int + troves_lte: Int + troves_in: [Int!] + troves_not_in: [Int!] + trovesByCollateral: [Int!] + trovesByCollateral_not: [Int!] + trovesByCollateral_contains: [Int!] + trovesByCollateral_contains_nocase: [Int!] + trovesByCollateral_not_contains: [Int!] + trovesByCollateral_not_contains_nocase: [Int!] + """Filter for the block changed event.""" + _change_block: BlockChangedFilter + and: [BorrowerInfo_filter] + or: [BorrowerInfo_filter] +} + +enum BorrowerInfo_orderBy { + id + troves + trovesByCollateral +} + scalar Bytes type Collateral { id: ID! + collIndex: Int! token: Token! minCollRatio: BigInt! troves(skip: Int = 0, first: Int = 100, orderBy: Trove_orderBy, orderDirection: OrderDirection, where: Trove_filter): [Trove!]! @@ -159,6 +201,7 @@ enum CollateralAddresses_orderBy { borrowerOperations collateral collateral__id + collateral__collIndex collateral__minCollRatio collateral__totalDeposited collateral__totalDebt @@ -178,6 +221,14 @@ input Collateral_filter { id_lte: ID id_in: [ID!] id_not_in: [ID!] + collIndex: Int + collIndex_not: Int + collIndex_gt: Int + collIndex_lt: Int + collIndex_gte: Int + collIndex_lte: Int + collIndex_in: [Int!] + collIndex_not_in: [Int!] token: String token_not: String token_gt: String @@ -233,6 +284,7 @@ input Collateral_filter { enum Collateral_orderBy { id + collIndex token token__id token__name @@ -448,6 +500,32 @@ type Query { """ subgraphError: _SubgraphErrorPolicy_! = deny ): [Trove!]! + borrowerInfo( + id: ID! + """ + The block at which the query should be executed. Can either be a `{ hash: Bytes }` value containing a block hash, a `{ number: Int }` containing the block number, or a `{ number_gte: Int }` containing the minimum block number. In the case of `number_gte`, the query will be executed on the latest block only if the subgraph has progressed to or past the minimum block number. Defaults to the latest block when omitted. + """ + block: Block_height + """ + Set to `allow` to receive data even if the subgraph has skipped over errors while syncing. + """ + subgraphError: _SubgraphErrorPolicy_! = deny + ): BorrowerInfo + borrowerInfos( + skip: Int = 0 + first: Int = 100 + orderBy: BorrowerInfo_orderBy + orderDirection: OrderDirection + where: BorrowerInfo_filter + """ + The block at which the query should be executed. Can either be a `{ hash: Bytes }` value containing a block hash, a `{ number: Int }` containing the block number, or a `{ number_gte: Int }` containing the minimum block number. In the case of `number_gte`, the query will be executed on the latest block only if the subgraph has progressed to or past the minimum block number. Defaults to the latest block when omitted. + """ + block: Block_height + """ + Set to `allow` to receive data even if the subgraph has skipped over errors while syncing. + """ + subgraphError: _SubgraphErrorPolicy_! = deny + ): [BorrowerInfo!]! """Access to subgraph metadata""" _meta(block: Block_height): _Meta_ } @@ -583,6 +661,32 @@ type Subscription { """ subgraphError: _SubgraphErrorPolicy_! = deny ): [Trove!]! + borrowerInfo( + id: ID! + """ + The block at which the query should be executed. Can either be a `{ hash: Bytes }` value containing a block hash, a `{ number: Int }` containing the block number, or a `{ number_gte: Int }` containing the minimum block number. In the case of `number_gte`, the query will be executed on the latest block only if the subgraph has progressed to or past the minimum block number. Defaults to the latest block when omitted. + """ + block: Block_height + """ + Set to `allow` to receive data even if the subgraph has skipped over errors while syncing. + """ + subgraphError: _SubgraphErrorPolicy_! = deny + ): BorrowerInfo + borrowerInfos( + skip: Int = 0 + first: Int = 100 + orderBy: BorrowerInfo_orderBy + orderDirection: OrderDirection + where: BorrowerInfo_filter + """ + The block at which the query should be executed. Can either be a `{ hash: Bytes }` value containing a block hash, a `{ number: Int }` containing the block number, or a `{ number_gte: Int }` containing the minimum block number. In the case of `number_gte`, the query will be executed on the latest block only if the subgraph has progressed to or past the minimum block number. Defaults to the latest block when omitted. + """ + block: Block_height + """ + Set to `allow` to receive data even if the subgraph has skipped over errors while syncing. + """ + subgraphError: _SubgraphErrorPolicy_! = deny + ): [BorrowerInfo!]! """Access to subgraph metadata""" _meta(block: Block_height): _Meta_ } @@ -689,6 +793,7 @@ enum Token_orderBy { id collateral collateral__id + collateral__collIndex collateral__minCollRatio collateral__totalDeposited collateral__totalDebt @@ -699,6 +804,7 @@ enum Token_orderBy { type Trove { id: ID! + troveId: String! borrower: Bytes! debt: BigInt! deposit: BigInt! @@ -718,6 +824,26 @@ input Trove_filter { id_lte: ID id_in: [ID!] id_not_in: [ID!] + troveId: String + troveId_not: String + troveId_gt: String + troveId_lt: String + troveId_gte: String + troveId_lte: String + troveId_in: [String!] + troveId_not_in: [String!] + troveId_contains: String + troveId_contains_nocase: String + troveId_not_contains: String + troveId_not_contains_nocase: String + troveId_starts_with: String + troveId_starts_with_nocase: String + troveId_not_starts_with: String + troveId_not_starts_with_nocase: String + troveId_ends_with: String + troveId_ends_with_nocase: String + troveId_not_ends_with: String + troveId_not_ends_with_nocase: String borrower: Bytes borrower_not: Bytes borrower_gt: Bytes @@ -805,6 +931,7 @@ input Trove_filter { enum Trove_orderBy { id + troveId borrower debt deposit @@ -814,6 +941,7 @@ enum Trove_orderBy { closedAt collateral collateral__id + collateral__collIndex collateral__minCollRatio collateral__totalDeposited collateral__totalDebt diff --git a/frontend/app/.graphclient/sources/liquity2/introspectionSchema.ts b/frontend/app/.graphclient/sources/liquity2/introspectionSchema.ts index 4d3350be..0075c32a 100644 --- a/frontend/app/.graphclient/sources/liquity2/introspectionSchema.ts +++ b/frontend/app/.graphclient/sources/liquity2/introspectionSchema.ts @@ -255,19 +255,11 @@ const schemaAST = { ], "directives": [] }, - { - "kind": "ScalarTypeDefinition", - "name": { - "kind": "Name", - "value": "Bytes" - }, - "directives": [] - }, { "kind": "ObjectTypeDefinition", "name": { "kind": "Name", - "value": "Collateral" + "value": "BorrowerInfo" }, "fields": [ { @@ -293,7 +285,7 @@ const schemaAST = { "kind": "FieldDefinition", "name": { "kind": "Name", - "value": "token" + "value": "troves" }, "arguments": [], "type": { @@ -302,7 +294,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "Token" + "value": "Int" } } }, @@ -312,112 +304,9 @@ const schemaAST = { "kind": "FieldDefinition", "name": { "kind": "Name", - "value": "minCollRatio" + "value": "trovesByCollateral" }, "arguments": [], - "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "BigInt" - } - } - }, - "directives": [] - }, - { - "kind": "FieldDefinition", - "name": { - "kind": "Name", - "value": "troves" - }, - "arguments": [ - { - "kind": "InputValueDefinition", - "name": { - "kind": "Name", - "value": "skip" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Int" - } - }, - "defaultValue": { - "kind": "IntValue", - "value": "0" - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "name": { - "kind": "Name", - "value": "first" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Int" - } - }, - "defaultValue": { - "kind": "IntValue", - "value": "100" - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "name": { - "kind": "Name", - "value": "orderBy" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Trove_orderBy" - } - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "name": { - "kind": "Name", - "value": "orderDirection" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "OrderDirection" - } - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "name": { - "kind": "Name", - "value": "where" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Trove_filter" - } - }, - "directives": [] - } - ], "type": { "kind": "NonNullType", "type": { @@ -428,256 +317,168 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "Trove" + "value": "Int" } } } } }, "directives": [] - }, + } + ], + "interfaces": [], + "directives": [] + }, + { + "kind": "InputObjectTypeDefinition", + "name": { + "kind": "Name", + "value": "BorrowerInfo_filter" + }, + "fields": [ { - "kind": "FieldDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "addresses" + "value": "id" }, - "arguments": [], "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "CollateralAddresses" - } + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "ID" } }, "directives": [] }, { - "kind": "FieldDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "totalDeposited" + "value": "id_not" }, - "arguments": [], "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "BigInt" - } + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "ID" } }, "directives": [] }, { - "kind": "FieldDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "totalDebt" + "value": "id_gt" }, - "arguments": [], "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "BigInt" - } + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "ID" } }, "directives": [] - } - ], - "interfaces": [], - "directives": [] - }, - { - "kind": "ObjectTypeDefinition", - "name": { - "kind": "Name", - "value": "CollateralAddresses" - }, - "fields": [ + }, { - "kind": "FieldDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id" + "value": "id_lt" }, - "arguments": [], "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "ID" - } + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "ID" } }, "directives": [] }, { - "kind": "FieldDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "borrowerOperations" + "value": "id_gte" }, - "arguments": [], "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Bytes" - } + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "ID" } }, "directives": [] }, { - "kind": "FieldDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "collateral" + "value": "id_lte" }, - "arguments": [], "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Collateral" - } + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "ID" } }, "directives": [] }, { - "kind": "FieldDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "sortedTroves" + "value": "id_in" }, - "arguments": [], "type": { - "kind": "NonNullType", + "kind": "ListType", "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Bytes" - } - } - }, - "directives": [] - }, - { - "kind": "FieldDefinition", - "name": { - "kind": "Name", - "value": "stabilityPool" - }, - "arguments": [], - "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Bytes" - } - } - }, - "directives": [] - }, - { - "kind": "FieldDefinition", - "name": { - "kind": "Name", - "value": "token" - }, - "arguments": [], - "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Bytes" + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "ID" + } } } }, "directives": [] }, { - "kind": "FieldDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "troveManager" + "value": "id_not_in" }, - "arguments": [], "type": { - "kind": "NonNullType", + "kind": "ListType", "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Bytes" + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "ID" + } } } }, "directives": [] }, - { - "kind": "FieldDefinition", - "name": { - "kind": "Name", - "value": "troveNft" - }, - "arguments": [], - "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Bytes" - } - } - }, - "directives": [] - } - ], - "interfaces": [], - "directives": [] - }, - { - "kind": "InputObjectTypeDefinition", - "name": { - "kind": "Name", - "value": "CollateralAddresses_filter" - }, - "fields": [ { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id" + "value": "troves" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "ID" + "value": "Int" } }, "directives": [] @@ -686,13 +487,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id_not" + "value": "troves_not" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "ID" + "value": "Int" } }, "directives": [] @@ -701,13 +502,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id_gt" + "value": "troves_gt" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "ID" + "value": "Int" } }, "directives": [] @@ -716,13 +517,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id_lt" + "value": "troves_lt" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "ID" + "value": "Int" } }, "directives": [] @@ -731,13 +532,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id_gte" + "value": "troves_gte" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "ID" + "value": "Int" } }, "directives": [] @@ -746,13 +547,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id_lte" + "value": "troves_lte" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "ID" + "value": "Int" } }, "directives": [] @@ -761,7 +562,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id_in" + "value": "troves_in" }, "type": { "kind": "ListType", @@ -771,7 +572,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "ID" + "value": "Int" } } } @@ -782,7 +583,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id_not_in" + "value": "troves_not_in" }, "type": { "kind": "ListType", @@ -792,7 +593,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "ID" + "value": "Int" } } } @@ -803,43 +604,19 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "borrowerOperations" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Bytes" - } - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "name": { - "kind": "Name", - "value": "borrowerOperations_not" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Bytes" - } - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "name": { - "kind": "Name", - "value": "borrowerOperations_gt" + "value": "trovesByCollateral" }, "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Bytes" + "kind": "ListType", + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Int" + } + } } }, "directives": [] @@ -848,13 +625,19 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "borrowerOperations_lt" + "value": "trovesByCollateral_not" }, "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Bytes" + "kind": "ListType", + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Int" + } + } } }, "directives": [] @@ -863,13 +646,19 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "borrowerOperations_gte" + "value": "trovesByCollateral_contains" }, "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Bytes" + "kind": "ListType", + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Int" + } + } } }, "directives": [] @@ -878,13 +667,19 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "borrowerOperations_lte" + "value": "trovesByCollateral_contains_nocase" }, "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Bytes" + "kind": "ListType", + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Int" + } + } } }, "directives": [] @@ -893,7 +688,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "borrowerOperations_in" + "value": "trovesByCollateral_not_contains" }, "type": { "kind": "ListType", @@ -903,7 +698,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "Bytes" + "value": "Int" } } } @@ -914,7 +709,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "borrowerOperations_not_in" + "value": "trovesByCollateral_not_contains_nocase" }, "type": { "kind": "ListType", @@ -924,7 +719,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "Bytes" + "value": "Int" } } } @@ -933,15 +728,20 @@ const schemaAST = { }, { "kind": "InputValueDefinition", + "description": { + "kind": "StringValue", + "value": "Filter for the block changed event.", + "block": true + }, "name": { "kind": "Name", - "value": "borrowerOperations_contains" + "value": "_change_block" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "Bytes" + "value": "BlockChangedFilter" } }, "directives": [] @@ -950,13 +750,16 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "borrowerOperations_not_contains" + "value": "and" }, "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Bytes" + "kind": "ListType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "BorrowerInfo_filter" + } } }, "directives": [] @@ -965,340 +768,499 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "collateral" + "value": "or" }, "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "String" + "kind": "ListType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "BorrowerInfo_filter" + } } }, "directives": [] - }, + } + ], + "directives": [] + }, + { + "kind": "EnumTypeDefinition", + "name": { + "kind": "Name", + "value": "BorrowerInfo_orderBy" + }, + "values": [ { - "kind": "InputValueDefinition", + "kind": "EnumValueDefinition", "name": { "kind": "Name", - "value": "collateral_not" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "String" - } + "value": "id" }, "directives": [] }, { - "kind": "InputValueDefinition", + "kind": "EnumValueDefinition", "name": { "kind": "Name", - "value": "collateral_gt" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "String" - } + "value": "troves" }, "directives": [] }, { - "kind": "InputValueDefinition", + "kind": "EnumValueDefinition", "name": { "kind": "Name", - "value": "collateral_lt" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "String" - } + "value": "trovesByCollateral" }, "directives": [] - }, + } + ], + "directives": [] + }, + { + "kind": "ScalarTypeDefinition", + "name": { + "kind": "Name", + "value": "Bytes" + }, + "directives": [] + }, + { + "kind": "ObjectTypeDefinition", + "name": { + "kind": "Name", + "value": "Collateral" + }, + "fields": [ { - "kind": "InputValueDefinition", + "kind": "FieldDefinition", "name": { "kind": "Name", - "value": "collateral_gte" + "value": "id" }, + "arguments": [], "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "String" + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "ID" + } } }, "directives": [] }, { - "kind": "InputValueDefinition", + "kind": "FieldDefinition", "name": { "kind": "Name", - "value": "collateral_lte" + "value": "collIndex" }, + "arguments": [], "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "String" + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Int" + } } }, "directives": [] }, { - "kind": "InputValueDefinition", + "kind": "FieldDefinition", "name": { "kind": "Name", - "value": "collateral_in" + "value": "token" }, + "arguments": [], "type": { - "kind": "ListType", + "kind": "NonNullType", "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "String" - } + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Token" } } }, "directives": [] }, { - "kind": "InputValueDefinition", + "kind": "FieldDefinition", "name": { "kind": "Name", - "value": "collateral_not_in" + "value": "minCollRatio" }, + "arguments": [], "type": { - "kind": "ListType", + "kind": "NonNullType", "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "String" - } + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "BigInt" } } }, "directives": [] }, { - "kind": "InputValueDefinition", + "kind": "FieldDefinition", "name": { "kind": "Name", - "value": "collateral_contains" + "value": "troves" }, + "arguments": [ + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "skip" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Int" + } + }, + "defaultValue": { + "kind": "IntValue", + "value": "0" + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "first" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Int" + } + }, + "defaultValue": { + "kind": "IntValue", + "value": "100" + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "orderBy" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Trove_orderBy" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "orderDirection" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "OrderDirection" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "where" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Trove_filter" + } + }, + "directives": [] + } + ], "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "String" + "kind": "NonNullType", + "type": { + "kind": "ListType", + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Trove" + } + } + } } }, "directives": [] }, { - "kind": "InputValueDefinition", + "kind": "FieldDefinition", "name": { "kind": "Name", - "value": "collateral_contains_nocase" + "value": "addresses" }, + "arguments": [], "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "String" + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "CollateralAddresses" + } } }, "directives": [] }, { - "kind": "InputValueDefinition", + "kind": "FieldDefinition", "name": { "kind": "Name", - "value": "collateral_not_contains" + "value": "totalDeposited" }, + "arguments": [], "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "String" + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "BigInt" + } } }, "directives": [] }, { - "kind": "InputValueDefinition", + "kind": "FieldDefinition", "name": { "kind": "Name", - "value": "collateral_not_contains_nocase" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "String" - } - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "name": { - "kind": "Name", - "value": "collateral_starts_with" + "value": "totalDebt" }, + "arguments": [], "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "String" + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "BigInt" + } } }, "directives": [] - }, + } + ], + "interfaces": [], + "directives": [] + }, + { + "kind": "ObjectTypeDefinition", + "name": { + "kind": "Name", + "value": "CollateralAddresses" + }, + "fields": [ { - "kind": "InputValueDefinition", + "kind": "FieldDefinition", "name": { "kind": "Name", - "value": "collateral_starts_with_nocase" + "value": "id" }, + "arguments": [], "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "String" + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "ID" + } } }, "directives": [] }, { - "kind": "InputValueDefinition", + "kind": "FieldDefinition", "name": { "kind": "Name", - "value": "collateral_not_starts_with" + "value": "borrowerOperations" }, + "arguments": [], "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "String" + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Bytes" + } } }, "directives": [] }, { - "kind": "InputValueDefinition", + "kind": "FieldDefinition", "name": { "kind": "Name", - "value": "collateral_not_starts_with_nocase" + "value": "collateral" }, + "arguments": [], "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "String" + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Collateral" + } } }, "directives": [] }, { - "kind": "InputValueDefinition", + "kind": "FieldDefinition", "name": { "kind": "Name", - "value": "collateral_ends_with" + "value": "sortedTroves" }, + "arguments": [], "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "String" + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Bytes" + } } }, "directives": [] }, { - "kind": "InputValueDefinition", + "kind": "FieldDefinition", "name": { "kind": "Name", - "value": "collateral_ends_with_nocase" + "value": "stabilityPool" }, + "arguments": [], "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "String" + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Bytes" + } } }, "directives": [] }, { - "kind": "InputValueDefinition", + "kind": "FieldDefinition", "name": { "kind": "Name", - "value": "collateral_not_ends_with" + "value": "token" }, + "arguments": [], "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "String" + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Bytes" + } } }, "directives": [] }, { - "kind": "InputValueDefinition", + "kind": "FieldDefinition", "name": { "kind": "Name", - "value": "collateral_not_ends_with_nocase" + "value": "troveManager" }, + "arguments": [], "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "String" + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Bytes" + } } }, "directives": [] }, { - "kind": "InputValueDefinition", + "kind": "FieldDefinition", "name": { "kind": "Name", - "value": "collateral_" + "value": "troveNft" }, + "arguments": [], "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Collateral_filter" + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Bytes" + } } }, "directives": [] - }, + } + ], + "interfaces": [], + "directives": [] + }, + { + "kind": "InputObjectTypeDefinition", + "name": { + "kind": "Name", + "value": "CollateralAddresses_filter" + }, + "fields": [ { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "sortedTroves" + "value": "id" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "Bytes" + "value": "ID" } }, "directives": [] @@ -1307,13 +1269,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "sortedTroves_not" + "value": "id_not" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "Bytes" + "value": "ID" } }, "directives": [] @@ -1322,13 +1284,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "sortedTroves_gt" + "value": "id_gt" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "Bytes" + "value": "ID" } }, "directives": [] @@ -1337,13 +1299,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "sortedTroves_lt" + "value": "id_lt" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "Bytes" + "value": "ID" } }, "directives": [] @@ -1352,13 +1314,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "sortedTroves_gte" + "value": "id_gte" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "Bytes" + "value": "ID" } }, "directives": [] @@ -1367,13 +1329,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "sortedTroves_lte" + "value": "id_lte" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "Bytes" + "value": "ID" } }, "directives": [] @@ -1382,7 +1344,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "sortedTroves_in" + "value": "id_in" }, "type": { "kind": "ListType", @@ -1392,7 +1354,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "Bytes" + "value": "ID" } } } @@ -1403,7 +1365,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "sortedTroves_not_in" + "value": "id_not_in" }, "type": { "kind": "ListType", @@ -1413,7 +1375,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "Bytes" + "value": "ID" } } } @@ -1424,7 +1386,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "sortedTroves_contains" + "value": "borrowerOperations" }, "type": { "kind": "NamedType", @@ -1439,7 +1401,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "sortedTroves_not_contains" + "value": "borrowerOperations_not" }, "type": { "kind": "NamedType", @@ -1454,7 +1416,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "stabilityPool" + "value": "borrowerOperations_gt" }, "type": { "kind": "NamedType", @@ -1469,7 +1431,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "stabilityPool_not" + "value": "borrowerOperations_lt" }, "type": { "kind": "NamedType", @@ -1484,7 +1446,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "stabilityPool_gt" + "value": "borrowerOperations_gte" }, "type": { "kind": "NamedType", @@ -1499,7 +1461,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "stabilityPool_lt" + "value": "borrowerOperations_lte" }, "type": { "kind": "NamedType", @@ -1514,13 +1476,19 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "stabilityPool_gte" + "value": "borrowerOperations_in" }, "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Bytes" + "kind": "ListType", + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Bytes" + } + } } }, "directives": [] @@ -1529,43 +1497,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "stabilityPool_lte" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Bytes" - } - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "name": { - "kind": "Name", - "value": "stabilityPool_in" - }, - "type": { - "kind": "ListType", - "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Bytes" - } - } - } - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "name": { - "kind": "Name", - "value": "stabilityPool_not_in" + "value": "borrowerOperations_not_in" }, "type": { "kind": "ListType", @@ -1586,7 +1518,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "stabilityPool_contains" + "value": "borrowerOperations_contains" }, "type": { "kind": "NamedType", @@ -1601,7 +1533,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "stabilityPool_not_contains" + "value": "borrowerOperations_not_contains" }, "type": { "kind": "NamedType", @@ -1616,13 +1548,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "token" + "value": "collateral" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "Bytes" + "value": "String" } }, "directives": [] @@ -1631,13 +1563,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "token_not" + "value": "collateral_not" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "Bytes" + "value": "String" } }, "directives": [] @@ -1646,13 +1578,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "token_gt" + "value": "collateral_gt" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "Bytes" + "value": "String" } }, "directives": [] @@ -1661,13 +1593,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "token_lt" + "value": "collateral_lt" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "Bytes" + "value": "String" } }, "directives": [] @@ -1676,13 +1608,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "token_gte" + "value": "collateral_gte" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "Bytes" + "value": "String" } }, "directives": [] @@ -1691,13 +1623,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "token_lte" + "value": "collateral_lte" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "Bytes" + "value": "String" } }, "directives": [] @@ -1706,7 +1638,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "token_in" + "value": "collateral_in" }, "type": { "kind": "ListType", @@ -1716,7 +1648,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "Bytes" + "value": "String" } } } @@ -1727,7 +1659,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "token_not_in" + "value": "collateral_not_in" }, "type": { "kind": "ListType", @@ -1737,7 +1669,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "Bytes" + "value": "String" } } } @@ -1748,13 +1680,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "token_contains" + "value": "collateral_contains" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "Bytes" + "value": "String" } }, "directives": [] @@ -1763,13 +1695,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "token_not_contains" + "value": "collateral_contains_nocase" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "Bytes" + "value": "String" } }, "directives": [] @@ -1778,13 +1710,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "troveManager" + "value": "collateral_not_contains" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "Bytes" + "value": "String" } }, "directives": [] @@ -1793,13 +1725,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "troveManager_not" + "value": "collateral_not_contains_nocase" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "Bytes" + "value": "String" } }, "directives": [] @@ -1808,13 +1740,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "troveManager_gt" + "value": "collateral_starts_with" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "Bytes" + "value": "String" } }, "directives": [] @@ -1823,13 +1755,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "troveManager_lt" + "value": "collateral_starts_with_nocase" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "Bytes" + "value": "String" } }, "directives": [] @@ -1838,13 +1770,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "troveManager_gte" + "value": "collateral_not_starts_with" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "Bytes" + "value": "String" } }, "directives": [] @@ -1853,13 +1785,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "troveManager_lte" + "value": "collateral_not_starts_with_nocase" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "Bytes" + "value": "String" } }, "directives": [] @@ -1868,19 +1800,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "troveManager_in" + "value": "collateral_ends_with" }, "type": { - "kind": "ListType", - "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Bytes" - } - } + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" } }, "directives": [] @@ -1889,19 +1815,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "troveManager_not_in" + "value": "collateral_ends_with_nocase" }, "type": { - "kind": "ListType", - "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Bytes" - } - } + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" } }, "directives": [] @@ -1910,13 +1830,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "troveManager_contains" + "value": "collateral_not_ends_with" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "Bytes" + "value": "String" } }, "directives": [] @@ -1925,13 +1845,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "troveManager_not_contains" + "value": "collateral_not_ends_with_nocase" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "Bytes" + "value": "String" } }, "directives": [] @@ -1940,7 +1860,22 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "troveNft" + "value": "collateral_" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Collateral_filter" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "sortedTroves" }, "type": { "kind": "NamedType", @@ -1955,7 +1890,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "troveNft_not" + "value": "sortedTroves_not" }, "type": { "kind": "NamedType", @@ -1970,7 +1905,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "troveNft_gt" + "value": "sortedTroves_gt" }, "type": { "kind": "NamedType", @@ -1985,7 +1920,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "troveNft_lt" + "value": "sortedTroves_lt" }, "type": { "kind": "NamedType", @@ -2000,7 +1935,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "troveNft_gte" + "value": "sortedTroves_gte" }, "type": { "kind": "NamedType", @@ -2015,7 +1950,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "troveNft_lte" + "value": "sortedTroves_lte" }, "type": { "kind": "NamedType", @@ -2030,7 +1965,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "troveNft_in" + "value": "sortedTroves_in" }, "type": { "kind": "ListType", @@ -2051,7 +1986,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "troveNft_not_in" + "value": "sortedTroves_not_in" }, "type": { "kind": "ListType", @@ -2072,7 +2007,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "troveNft_contains" + "value": "sortedTroves_contains" }, "type": { "kind": "NamedType", @@ -2087,7 +2022,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "troveNft_not_contains" + "value": "sortedTroves_not_contains" }, "type": { "kind": "NamedType", @@ -2100,20 +2035,15 @@ const schemaAST = { }, { "kind": "InputValueDefinition", - "description": { - "kind": "StringValue", - "value": "Filter for the block changed event.", - "block": true - }, "name": { "kind": "Name", - "value": "_change_block" + "value": "stabilityPool" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "BlockChangedFilter" + "value": "Bytes" } }, "directives": [] @@ -2122,16 +2052,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "and" + "value": "stabilityPool_not" }, "type": { - "kind": "ListType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "CollateralAddresses_filter" - } + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Bytes" } }, "directives": [] @@ -2140,147 +2067,145 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "or" + "value": "stabilityPool_gt" }, "type": { - "kind": "ListType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "CollateralAddresses_filter" - } + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Bytes" } }, "directives": [] - } - ], - "directives": [] - }, - { - "kind": "EnumTypeDefinition", - "name": { - "kind": "Name", - "value": "CollateralAddresses_orderBy" - }, - "values": [ - { - "kind": "EnumValueDefinition", - "name": { - "kind": "Name", - "value": "id" - }, - "directives": [] }, { - "kind": "EnumValueDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "borrowerOperations" + "value": "stabilityPool_lt" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Bytes" + } }, "directives": [] }, { - "kind": "EnumValueDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "collateral" + "value": "stabilityPool_gte" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Bytes" + } }, "directives": [] }, { - "kind": "EnumValueDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "collateral__id" + "value": "stabilityPool_lte" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Bytes" + } }, "directives": [] }, { - "kind": "EnumValueDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "collateral__minCollRatio" + "value": "stabilityPool_in" }, - "directives": [] - }, - { - "kind": "EnumValueDefinition", - "name": { - "kind": "Name", - "value": "collateral__totalDeposited" + "type": { + "kind": "ListType", + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Bytes" + } + } + } }, "directives": [] }, { - "kind": "EnumValueDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "collateral__totalDebt" + "value": "stabilityPool_not_in" }, - "directives": [] - }, - { - "kind": "EnumValueDefinition", - "name": { - "kind": "Name", - "value": "sortedTroves" + "type": { + "kind": "ListType", + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Bytes" + } + } + } }, "directives": [] }, { - "kind": "EnumValueDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "stabilityPool" + "value": "stabilityPool_contains" }, - "directives": [] - }, - { - "kind": "EnumValueDefinition", - "name": { - "kind": "Name", - "value": "token" + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Bytes" + } }, "directives": [] }, { - "kind": "EnumValueDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "troveManager" + "value": "stabilityPool_not_contains" }, - "directives": [] - }, - { - "kind": "EnumValueDefinition", - "name": { - "kind": "Name", - "value": "troveNft" + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Bytes" + } }, "directives": [] - } - ], - "directives": [] - }, - { - "kind": "InputObjectTypeDefinition", - "name": { - "kind": "Name", - "value": "Collateral_filter" - }, - "fields": [ + }, { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id" + "value": "token" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "ID" + "value": "Bytes" } }, "directives": [] @@ -2289,13 +2214,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id_not" + "value": "token_not" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "ID" + "value": "Bytes" } }, "directives": [] @@ -2304,13 +2229,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id_gt" + "value": "token_gt" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "ID" + "value": "Bytes" } }, "directives": [] @@ -2319,13 +2244,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id_lt" + "value": "token_lt" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "ID" + "value": "Bytes" } }, "directives": [] @@ -2334,13 +2259,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id_gte" + "value": "token_gte" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "ID" + "value": "Bytes" } }, "directives": [] @@ -2349,13 +2274,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id_lte" + "value": "token_lte" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "ID" + "value": "Bytes" } }, "directives": [] @@ -2364,7 +2289,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id_in" + "value": "token_in" }, "type": { "kind": "ListType", @@ -2374,7 +2299,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "ID" + "value": "Bytes" } } } @@ -2385,7 +2310,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id_not_in" + "value": "token_not_in" }, "type": { "kind": "ListType", @@ -2395,7 +2320,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "ID" + "value": "Bytes" } } } @@ -2406,13 +2331,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "token" + "value": "token_contains" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "String" + "value": "Bytes" } }, "directives": [] @@ -2421,13 +2346,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "token_not" + "value": "token_not_contains" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "String" + "value": "Bytes" } }, "directives": [] @@ -2436,13 +2361,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "token_gt" + "value": "troveManager" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "String" + "value": "Bytes" } }, "directives": [] @@ -2451,13 +2376,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "token_lt" + "value": "troveManager_not" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "String" + "value": "Bytes" } }, "directives": [] @@ -2466,13 +2391,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "token_gte" + "value": "troveManager_gt" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "String" + "value": "Bytes" } }, "directives": [] @@ -2481,13 +2406,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "token_lte" + "value": "troveManager_lt" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "String" + "value": "Bytes" } }, "directives": [] @@ -2496,7 +2421,37 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "token_in" + "value": "troveManager_gte" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Bytes" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "troveManager_lte" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Bytes" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "troveManager_in" }, "type": { "kind": "ListType", @@ -2506,7 +2461,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "String" + "value": "Bytes" } } } @@ -2517,7 +2472,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "token_not_in" + "value": "troveManager_not_in" }, "type": { "kind": "ListType", @@ -2527,7 +2482,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "String" + "value": "Bytes" } } } @@ -2538,13 +2493,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "token_contains" + "value": "troveManager_contains" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "String" + "value": "Bytes" } }, "directives": [] @@ -2553,13 +2508,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "token_contains_nocase" + "value": "troveManager_not_contains" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "String" + "value": "Bytes" } }, "directives": [] @@ -2568,13 +2523,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "token_not_contains" + "value": "troveNft" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "String" + "value": "Bytes" } }, "directives": [] @@ -2583,13 +2538,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "token_not_contains_nocase" + "value": "troveNft_not" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "String" + "value": "Bytes" } }, "directives": [] @@ -2598,13 +2553,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "token_starts_with" + "value": "troveNft_gt" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "String" + "value": "Bytes" } }, "directives": [] @@ -2613,13 +2568,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "token_starts_with_nocase" + "value": "troveNft_lt" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "String" + "value": "Bytes" } }, "directives": [] @@ -2628,13 +2583,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "token_not_starts_with" + "value": "troveNft_gte" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "String" + "value": "Bytes" } }, "directives": [] @@ -2643,13 +2598,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "token_not_starts_with_nocase" + "value": "troveNft_lte" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "String" + "value": "Bytes" } }, "directives": [] @@ -2658,13 +2613,19 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "token_ends_with" + "value": "troveNft_in" }, "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "String" + "kind": "ListType", + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Bytes" + } + } } }, "directives": [] @@ -2673,13 +2634,19 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "token_ends_with_nocase" + "value": "troveNft_not_in" }, "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "String" + "kind": "ListType", + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Bytes" + } + } } }, "directives": [] @@ -2688,13 +2655,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "token_not_ends_with" + "value": "troveNft_contains" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "String" + "value": "Bytes" } }, "directives": [] @@ -2703,28 +2670,33 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "token_not_ends_with_nocase" + "value": "troveNft_not_contains" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "String" + "value": "Bytes" } }, "directives": [] }, { "kind": "InputValueDefinition", - "name": { + "description": { + "kind": "StringValue", + "value": "Filter for the block changed event.", + "block": true + }, + "name": { "kind": "Name", - "value": "token_" + "value": "_change_block" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "Token_filter" + "value": "BlockChangedFilter" } }, "directives": [] @@ -2733,13 +2705,16 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "minCollRatio" + "value": "and" }, "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "BigInt" + "kind": "ListType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "CollateralAddresses_filter" + } } }, "directives": [] @@ -2748,160 +2723,155 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "minCollRatio_not" + "value": "or" }, "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "BigInt" + "kind": "ListType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "CollateralAddresses_filter" + } } }, "directives": [] - }, + } + ], + "directives": [] + }, + { + "kind": "EnumTypeDefinition", + "name": { + "kind": "Name", + "value": "CollateralAddresses_orderBy" + }, + "values": [ { - "kind": "InputValueDefinition", + "kind": "EnumValueDefinition", "name": { "kind": "Name", - "value": "minCollRatio_gt" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "BigInt" - } + "value": "id" }, "directives": [] }, { - "kind": "InputValueDefinition", + "kind": "EnumValueDefinition", "name": { "kind": "Name", - "value": "minCollRatio_lt" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "BigInt" - } + "value": "borrowerOperations" }, "directives": [] }, { - "kind": "InputValueDefinition", + "kind": "EnumValueDefinition", "name": { "kind": "Name", - "value": "minCollRatio_gte" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "BigInt" - } + "value": "collateral" }, "directives": [] }, { - "kind": "InputValueDefinition", + "kind": "EnumValueDefinition", "name": { "kind": "Name", - "value": "minCollRatio_lte" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "BigInt" - } + "value": "collateral__id" }, "directives": [] }, { - "kind": "InputValueDefinition", + "kind": "EnumValueDefinition", "name": { "kind": "Name", - "value": "minCollRatio_in" + "value": "collateral__collIndex" }, - "type": { - "kind": "ListType", - "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "BigInt" - } - } - } + "directives": [] + }, + { + "kind": "EnumValueDefinition", + "name": { + "kind": "Name", + "value": "collateral__minCollRatio" }, "directives": [] }, { - "kind": "InputValueDefinition", + "kind": "EnumValueDefinition", "name": { "kind": "Name", - "value": "minCollRatio_not_in" + "value": "collateral__totalDeposited" }, - "type": { - "kind": "ListType", - "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "BigInt" - } - } - } + "directives": [] + }, + { + "kind": "EnumValueDefinition", + "name": { + "kind": "Name", + "value": "collateral__totalDebt" }, "directives": [] }, { - "kind": "InputValueDefinition", + "kind": "EnumValueDefinition", "name": { "kind": "Name", - "value": "troves_" + "value": "sortedTroves" }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Trove_filter" - } + "directives": [] + }, + { + "kind": "EnumValueDefinition", + "name": { + "kind": "Name", + "value": "stabilityPool" }, "directives": [] }, { - "kind": "InputValueDefinition", + "kind": "EnumValueDefinition", "name": { "kind": "Name", - "value": "addresses_" + "value": "token" }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "CollateralAddresses_filter" - } + "directives": [] + }, + { + "kind": "EnumValueDefinition", + "name": { + "kind": "Name", + "value": "troveManager" }, "directives": [] }, + { + "kind": "EnumValueDefinition", + "name": { + "kind": "Name", + "value": "troveNft" + }, + "directives": [] + } + ], + "directives": [] + }, + { + "kind": "InputObjectTypeDefinition", + "name": { + "kind": "Name", + "value": "Collateral_filter" + }, + "fields": [ { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "totalDeposited" + "value": "id" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "BigInt" + "value": "ID" } }, "directives": [] @@ -2910,13 +2880,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "totalDeposited_not" + "value": "id_not" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "BigInt" + "value": "ID" } }, "directives": [] @@ -2925,13 +2895,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "totalDeposited_gt" + "value": "id_gt" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "BigInt" + "value": "ID" } }, "directives": [] @@ -2940,13 +2910,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "totalDeposited_lt" + "value": "id_lt" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "BigInt" + "value": "ID" } }, "directives": [] @@ -2955,13 +2925,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "totalDeposited_gte" + "value": "id_gte" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "BigInt" + "value": "ID" } }, "directives": [] @@ -2970,13 +2940,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "totalDeposited_lte" + "value": "id_lte" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "BigInt" + "value": "ID" } }, "directives": [] @@ -2985,7 +2955,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "totalDeposited_in" + "value": "id_in" }, "type": { "kind": "ListType", @@ -2995,7 +2965,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "BigInt" + "value": "ID" } } } @@ -3006,7 +2976,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "totalDeposited_not_in" + "value": "id_not_in" }, "type": { "kind": "ListType", @@ -3016,7 +2986,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "BigInt" + "value": "ID" } } } @@ -3027,13 +2997,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "totalDebt" + "value": "collIndex" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "BigInt" + "value": "Int" } }, "directives": [] @@ -3042,13 +3012,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "totalDebt_not" + "value": "collIndex_not" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "BigInt" + "value": "Int" } }, "directives": [] @@ -3057,13 +3027,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "totalDebt_gt" + "value": "collIndex_gt" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "BigInt" + "value": "Int" } }, "directives": [] @@ -3072,13 +3042,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "totalDebt_lt" + "value": "collIndex_lt" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "BigInt" + "value": "Int" } }, "directives": [] @@ -3087,13 +3057,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "totalDebt_gte" + "value": "collIndex_gte" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "BigInt" + "value": "Int" } }, "directives": [] @@ -3102,13 +3072,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "totalDebt_lte" + "value": "collIndex_lte" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "BigInt" + "value": "Int" } }, "directives": [] @@ -3117,7 +3087,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "totalDebt_in" + "value": "collIndex_in" }, "type": { "kind": "ListType", @@ -3127,7 +3097,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "BigInt" + "value": "Int" } } } @@ -3138,7 +3108,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "totalDebt_not_in" + "value": "collIndex_not_in" }, "type": { "kind": "ListType", @@ -3148,7 +3118,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "BigInt" + "value": "Int" } } } @@ -3157,20 +3127,15 @@ const schemaAST = { }, { "kind": "InputValueDefinition", - "description": { - "kind": "StringValue", - "value": "Filter for the block changed event.", - "block": true - }, "name": { "kind": "Name", - "value": "_change_block" + "value": "token" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "BlockChangedFilter" + "value": "String" } }, "directives": [] @@ -3179,16 +3144,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "and" + "value": "token_not" }, "type": { - "kind": "ListType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Collateral_filter" - } + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" } }, "directives": [] @@ -3197,295 +3159,310 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "or" + "value": "token_gt" }, "type": { - "kind": "ListType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Collateral_filter" - } + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" } }, "directives": [] - } - ], - "directives": [] - }, - { - "kind": "EnumTypeDefinition", - "name": { - "kind": "Name", - "value": "Collateral_orderBy" - }, - "values": [ + }, { - "kind": "EnumValueDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id" + "value": "token_lt" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" + } }, "directives": [] }, { - "kind": "EnumValueDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "token" + "value": "token_gte" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" + } }, "directives": [] }, { - "kind": "EnumValueDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "token__id" + "value": "token_lte" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" + } }, "directives": [] }, { - "kind": "EnumValueDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "token__name" + "value": "token_in" + }, + "type": { + "kind": "ListType", + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" + } + } + } }, "directives": [] }, { - "kind": "EnumValueDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "token__symbol" + "value": "token_not_in" + }, + "type": { + "kind": "ListType", + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" + } + } + } }, "directives": [] }, { - "kind": "EnumValueDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "token__decimals" + "value": "token_contains" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" + } }, "directives": [] }, { - "kind": "EnumValueDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "minCollRatio" + "value": "token_contains_nocase" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" + } }, "directives": [] }, { - "kind": "EnumValueDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "troves" + "value": "token_not_contains" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" + } }, "directives": [] }, { - "kind": "EnumValueDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "addresses" + "value": "token_not_contains_nocase" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" + } }, "directives": [] }, { - "kind": "EnumValueDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "addresses__id" + "value": "token_starts_with" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" + } }, "directives": [] }, { - "kind": "EnumValueDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "addresses__borrowerOperations" + "value": "token_starts_with_nocase" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" + } }, "directives": [] }, { - "kind": "EnumValueDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "addresses__sortedTroves" + "value": "token_not_starts_with" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" + } }, "directives": [] }, { - "kind": "EnumValueDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "addresses__stabilityPool" + "value": "token_not_starts_with_nocase" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" + } }, "directives": [] }, { - "kind": "EnumValueDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "addresses__token" + "value": "token_ends_with" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" + } }, "directives": [] }, { - "kind": "EnumValueDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "addresses__troveManager" + "value": "token_ends_with_nocase" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" + } }, "directives": [] }, { - "kind": "EnumValueDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "addresses__troveNft" + "value": "token_not_ends_with" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" + } }, "directives": [] }, { - "kind": "EnumValueDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "totalDeposited" + "value": "token_not_ends_with_nocase" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" + } }, "directives": [] }, { - "kind": "EnumValueDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "totalDebt" - }, - "directives": [] - } - ], - "directives": [] - }, - { - "kind": "ScalarTypeDefinition", - "description": { - "kind": "StringValue", - "value": "8 bytes signed integer\n", - "block": true - }, - "name": { - "kind": "Name", - "value": "Int8" - }, - "directives": [] - }, - { - "kind": "ObjectTypeDefinition", - "name": { - "kind": "Name", - "value": "InterestRateBracket" - }, - "fields": [ - { - "kind": "FieldDefinition", - "name": { - "kind": "Name", - "value": "id" - }, - "arguments": [], - "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "ID" - } - } - }, - "directives": [] - }, - { - "kind": "FieldDefinition", - "name": { - "kind": "Name", - "value": "rate" - }, - "arguments": [], - "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "BigInt" - } - } - }, - "directives": [] - }, - { - "kind": "FieldDefinition", - "name": { - "kind": "Name", - "value": "totalDebt" - }, - "arguments": [], - "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "BigInt" - } - } + "value": "token_" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Token_filter" + } }, "directives": [] }, - { - "kind": "FieldDefinition", - "name": { - "kind": "Name", - "value": "totalTroves" - }, - "arguments": [], - "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Int" - } - } - }, - "directives": [] - } - ], - "interfaces": [], - "directives": [] - }, - { - "kind": "InputObjectTypeDefinition", - "name": { - "kind": "Name", - "value": "InterestRateBracket_filter" - }, - "fields": [ { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id" + "value": "minCollRatio" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "ID" + "value": "BigInt" } }, "directives": [] @@ -3494,13 +3471,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id_not" + "value": "minCollRatio_not" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "ID" + "value": "BigInt" } }, "directives": [] @@ -3509,13 +3486,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id_gt" + "value": "minCollRatio_gt" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "ID" + "value": "BigInt" } }, "directives": [] @@ -3524,13 +3501,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id_lt" + "value": "minCollRatio_lt" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "ID" + "value": "BigInt" } }, "directives": [] @@ -3539,13 +3516,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id_gte" + "value": "minCollRatio_gte" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "ID" + "value": "BigInt" } }, "directives": [] @@ -3554,13 +3531,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id_lte" + "value": "minCollRatio_lte" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "ID" + "value": "BigInt" } }, "directives": [] @@ -3569,7 +3546,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id_in" + "value": "minCollRatio_in" }, "type": { "kind": "ListType", @@ -3579,7 +3556,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "ID" + "value": "BigInt" } } } @@ -3590,7 +3567,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id_not_in" + "value": "minCollRatio_not_in" }, "type": { "kind": "ListType", @@ -3600,7 +3577,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "ID" + "value": "BigInt" } } } @@ -3611,7 +3588,37 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "rate" + "value": "troves_" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Trove_filter" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "addresses_" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "CollateralAddresses_filter" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "totalDeposited" }, "type": { "kind": "NamedType", @@ -3626,7 +3633,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "rate_not" + "value": "totalDeposited_not" }, "type": { "kind": "NamedType", @@ -3641,7 +3648,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "rate_gt" + "value": "totalDeposited_gt" }, "type": { "kind": "NamedType", @@ -3656,7 +3663,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "rate_lt" + "value": "totalDeposited_lt" }, "type": { "kind": "NamedType", @@ -3671,7 +3678,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "rate_gte" + "value": "totalDeposited_gte" }, "type": { "kind": "NamedType", @@ -3686,7 +3693,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "rate_lte" + "value": "totalDeposited_lte" }, "type": { "kind": "NamedType", @@ -3701,7 +3708,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "rate_in" + "value": "totalDeposited_in" }, "type": { "kind": "ListType", @@ -3722,7 +3729,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "rate_not_in" + "value": "totalDeposited_not_in" }, "type": { "kind": "ListType", @@ -3873,15 +3880,20 @@ const schemaAST = { }, { "kind": "InputValueDefinition", + "description": { + "kind": "StringValue", + "value": "Filter for the block changed event.", + "block": true + }, "name": { "kind": "Name", - "value": "totalTroves" + "value": "_change_block" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "Int" + "value": "BlockChangedFilter" } }, "directives": [] @@ -3890,13 +3902,16 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "totalTroves_not" + "value": "and" }, "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Int" + "kind": "ListType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Collateral_filter" + } } }, "directives": [] @@ -3905,175 +3920,139 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "totalTroves_gt" + "value": "or" }, "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Int" + "kind": "ListType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Collateral_filter" + } } }, "directives": [] - }, + } + ], + "directives": [] + }, + { + "kind": "EnumTypeDefinition", + "name": { + "kind": "Name", + "value": "Collateral_orderBy" + }, + "values": [ { - "kind": "InputValueDefinition", + "kind": "EnumValueDefinition", "name": { "kind": "Name", - "value": "totalTroves_lt" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Int" - } + "value": "id" }, "directives": [] }, { - "kind": "InputValueDefinition", + "kind": "EnumValueDefinition", "name": { "kind": "Name", - "value": "totalTroves_gte" + "value": "collIndex" }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Int" - } + "directives": [] + }, + { + "kind": "EnumValueDefinition", + "name": { + "kind": "Name", + "value": "token" }, "directives": [] }, { - "kind": "InputValueDefinition", + "kind": "EnumValueDefinition", "name": { "kind": "Name", - "value": "totalTroves_lte" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Int" - } + "value": "token__id" }, "directives": [] }, { - "kind": "InputValueDefinition", + "kind": "EnumValueDefinition", "name": { "kind": "Name", - "value": "totalTroves_in" - }, - "type": { - "kind": "ListType", - "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Int" - } - } - } + "value": "token__name" }, "directives": [] }, { - "kind": "InputValueDefinition", + "kind": "EnumValueDefinition", "name": { "kind": "Name", - "value": "totalTroves_not_in" - }, - "type": { - "kind": "ListType", - "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Int" - } - } - } + "value": "token__symbol" }, "directives": [] }, { - "kind": "InputValueDefinition", - "description": { - "kind": "StringValue", - "value": "Filter for the block changed event.", - "block": true + "kind": "EnumValueDefinition", + "name": { + "kind": "Name", + "value": "token__decimals" }, + "directives": [] + }, + { + "kind": "EnumValueDefinition", "name": { "kind": "Name", - "value": "_change_block" + "value": "minCollRatio" }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "BlockChangedFilter" - } + "directives": [] + }, + { + "kind": "EnumValueDefinition", + "name": { + "kind": "Name", + "value": "troves" }, "directives": [] }, { - "kind": "InputValueDefinition", + "kind": "EnumValueDefinition", "name": { "kind": "Name", - "value": "and" + "value": "addresses" }, - "type": { - "kind": "ListType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "InterestRateBracket_filter" - } - } + "directives": [] + }, + { + "kind": "EnumValueDefinition", + "name": { + "kind": "Name", + "value": "addresses__id" }, "directives": [] }, { - "kind": "InputValueDefinition", + "kind": "EnumValueDefinition", "name": { "kind": "Name", - "value": "or" + "value": "addresses__borrowerOperations" }, - "type": { - "kind": "ListType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "InterestRateBracket_filter" - } - } + "directives": [] + }, + { + "kind": "EnumValueDefinition", + "name": { + "kind": "Name", + "value": "addresses__sortedTroves" }, "directives": [] - } - ], - "directives": [] - }, - { - "kind": "EnumTypeDefinition", - "name": { - "kind": "Name", - "value": "InterestRateBracket_orderBy" - }, - "values": [ + }, { "kind": "EnumValueDefinition", "name": { "kind": "Name", - "value": "id" + "value": "addresses__stabilityPool" }, "directives": [] }, @@ -4081,7 +4060,7 @@ const schemaAST = { "kind": "EnumValueDefinition", "name": { "kind": "Name", - "value": "rate" + "value": "addresses__token" }, "directives": [] }, @@ -4089,7 +4068,7 @@ const schemaAST = { "kind": "EnumValueDefinition", "name": { "kind": "Name", - "value": "totalDebt" + "value": "addresses__troveManager" }, "directives": [] }, @@ -4097,30 +4076,15 @@ const schemaAST = { "kind": "EnumValueDefinition", "name": { "kind": "Name", - "value": "totalTroves" + "value": "addresses__troveNft" }, "directives": [] - } - ], - "directives": [] - }, - { - "kind": "EnumTypeDefinition", - "description": { - "kind": "StringValue", - "value": "Defines the order direction, either ascending or descending", - "block": true - }, - "name": { - "kind": "Name", - "value": "OrderDirection" - }, - "values": [ + }, { "kind": "EnumValueDefinition", "name": { "kind": "Name", - "value": "asc" + "value": "totalDeposited" }, "directives": [] }, @@ -4128,98 +4092,48 @@ const schemaAST = { "kind": "EnumValueDefinition", "name": { "kind": "Name", - "value": "desc" + "value": "totalDebt" }, "directives": [] } ], "directives": [] }, + { + "kind": "ScalarTypeDefinition", + "description": { + "kind": "StringValue", + "value": "8 bytes signed integer\n", + "block": true + }, + "name": { + "kind": "Name", + "value": "Int8" + }, + "directives": [] + }, { "kind": "ObjectTypeDefinition", "name": { "kind": "Name", - "value": "Query" + "value": "InterestRateBracket" }, "fields": [ { "kind": "FieldDefinition", "name": { "kind": "Name", - "value": "collateral" + "value": "id" }, - "arguments": [ - { - "kind": "InputValueDefinition", - "name": { - "kind": "Name", - "value": "id" - }, - "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "ID" - } - } - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "description": { - "kind": "StringValue", - "value": "The block at which the query should be executed. Can either be a `{ hash: Bytes }` value containing a block hash, a `{ number: Int }` containing the block number, or a `{ number_gte: Int }` containing the minimum block number. In the case of `number_gte`, the query will be executed on the latest block only if the subgraph has progressed to or past the minimum block number. Defaults to the latest block when omitted.", - "block": true - }, - "name": { - "kind": "Name", - "value": "block" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Block_height" - } - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "description": { - "kind": "StringValue", - "value": "Set to `allow` to receive data even if the subgraph has skipped over errors while syncing.", - "block": true - }, + "arguments": [], + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", "name": { "kind": "Name", - "value": "subgraphError" - }, - "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "_SubgraphErrorPolicy_" - } - } - }, - "defaultValue": { - "kind": "EnumValue", - "value": "deny" - }, - "directives": [] - } - ], - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Collateral" + "value": "ID" + } } }, "directives": [] @@ -4228,153 +4142,35 @@ const schemaAST = { "kind": "FieldDefinition", "name": { "kind": "Name", - "value": "collaterals" + "value": "rate" }, - "arguments": [ - { - "kind": "InputValueDefinition", + "arguments": [], + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", "name": { "kind": "Name", - "value": "skip" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Int" - } - }, - "defaultValue": { - "kind": "IntValue", - "value": "0" - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "name": { - "kind": "Name", - "value": "first" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Int" - } - }, - "defaultValue": { - "kind": "IntValue", - "value": "100" - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "name": { - "kind": "Name", - "value": "orderBy" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Collateral_orderBy" - } - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "name": { - "kind": "Name", - "value": "orderDirection" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "OrderDirection" - } - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "name": { - "kind": "Name", - "value": "where" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Collateral_filter" - } - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "description": { - "kind": "StringValue", - "value": "The block at which the query should be executed. Can either be a `{ hash: Bytes }` value containing a block hash, a `{ number: Int }` containing the block number, or a `{ number_gte: Int }` containing the minimum block number. In the case of `number_gte`, the query will be executed on the latest block only if the subgraph has progressed to or past the minimum block number. Defaults to the latest block when omitted.", - "block": true - }, - "name": { - "kind": "Name", - "value": "block" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Block_height" - } - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "description": { - "kind": "StringValue", - "value": "Set to `allow` to receive data even if the subgraph has skipped over errors while syncing.", - "block": true - }, - "name": { - "kind": "Name", - "value": "subgraphError" - }, - "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "_SubgraphErrorPolicy_" - } - } - }, - "defaultValue": { - "kind": "EnumValue", - "value": "deny" - }, - "directives": [] + "value": "BigInt" + } } - ], + }, + "directives": [] + }, + { + "kind": "FieldDefinition", + "name": { + "kind": "Name", + "value": "totalDebt" + }, + "arguments": [], "type": { "kind": "NonNullType", "type": { - "kind": "ListType", - "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Collateral" - } - } + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "BigInt" } } }, @@ -4384,97 +4180,2270 @@ const schemaAST = { "kind": "FieldDefinition", "name": { "kind": "Name", - "value": "token" + "value": "totalTroves" }, - "arguments": [ - { - "kind": "InputValueDefinition", - "name": { - "kind": "Name", - "value": "id" - }, - "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "ID" - } - } - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "description": { - "kind": "StringValue", - "value": "The block at which the query should be executed. Can either be a `{ hash: Bytes }` value containing a block hash, a `{ number: Int }` containing the block number, or a `{ number_gte: Int }` containing the minimum block number. In the case of `number_gte`, the query will be executed on the latest block only if the subgraph has progressed to or past the minimum block number. Defaults to the latest block when omitted.", - "block": true - }, - "name": { - "kind": "Name", - "value": "block" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Block_height" - } - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "description": { - "kind": "StringValue", - "value": "Set to `allow` to receive data even if the subgraph has skipped over errors while syncing.", - "block": true - }, + "arguments": [], + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", "name": { "kind": "Name", - "value": "subgraphError" - }, - "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "_SubgraphErrorPolicy_" - } - } - }, - "defaultValue": { - "kind": "EnumValue", - "value": "deny" - }, - "directives": [] + "value": "Int" + } } - ], + }, + "directives": [] + } + ], + "interfaces": [], + "directives": [] + }, + { + "kind": "InputObjectTypeDefinition", + "name": { + "kind": "Name", + "value": "InterestRateBracket_filter" + }, + "fields": [ + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "id" + }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "Token" + "value": "ID" } }, "directives": [] }, { - "kind": "FieldDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "tokens" + "value": "id_not" }, - "arguments": [ - { - "kind": "InputValueDefinition", - "name": { - "kind": "Name", - "value": "skip" - }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "ID" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "id_gt" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "ID" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "id_lt" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "ID" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "id_gte" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "ID" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "id_lte" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "ID" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "id_in" + }, + "type": { + "kind": "ListType", + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "ID" + } + } + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "id_not_in" + }, + "type": { + "kind": "ListType", + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "ID" + } + } + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "rate" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "BigInt" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "rate_not" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "BigInt" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "rate_gt" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "BigInt" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "rate_lt" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "BigInt" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "rate_gte" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "BigInt" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "rate_lte" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "BigInt" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "rate_in" + }, + "type": { + "kind": "ListType", + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "BigInt" + } + } + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "rate_not_in" + }, + "type": { + "kind": "ListType", + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "BigInt" + } + } + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "totalDebt" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "BigInt" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "totalDebt_not" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "BigInt" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "totalDebt_gt" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "BigInt" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "totalDebt_lt" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "BigInt" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "totalDebt_gte" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "BigInt" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "totalDebt_lte" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "BigInt" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "totalDebt_in" + }, + "type": { + "kind": "ListType", + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "BigInt" + } + } + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "totalDebt_not_in" + }, + "type": { + "kind": "ListType", + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "BigInt" + } + } + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "totalTroves" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Int" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "totalTroves_not" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Int" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "totalTroves_gt" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Int" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "totalTroves_lt" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Int" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "totalTroves_gte" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Int" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "totalTroves_lte" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Int" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "totalTroves_in" + }, + "type": { + "kind": "ListType", + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Int" + } + } + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "totalTroves_not_in" + }, + "type": { + "kind": "ListType", + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Int" + } + } + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "description": { + "kind": "StringValue", + "value": "Filter for the block changed event.", + "block": true + }, + "name": { + "kind": "Name", + "value": "_change_block" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "BlockChangedFilter" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "and" + }, + "type": { + "kind": "ListType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "InterestRateBracket_filter" + } + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "or" + }, + "type": { + "kind": "ListType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "InterestRateBracket_filter" + } + } + }, + "directives": [] + } + ], + "directives": [] + }, + { + "kind": "EnumTypeDefinition", + "name": { + "kind": "Name", + "value": "InterestRateBracket_orderBy" + }, + "values": [ + { + "kind": "EnumValueDefinition", + "name": { + "kind": "Name", + "value": "id" + }, + "directives": [] + }, + { + "kind": "EnumValueDefinition", + "name": { + "kind": "Name", + "value": "rate" + }, + "directives": [] + }, + { + "kind": "EnumValueDefinition", + "name": { + "kind": "Name", + "value": "totalDebt" + }, + "directives": [] + }, + { + "kind": "EnumValueDefinition", + "name": { + "kind": "Name", + "value": "totalTroves" + }, + "directives": [] + } + ], + "directives": [] + }, + { + "kind": "EnumTypeDefinition", + "description": { + "kind": "StringValue", + "value": "Defines the order direction, either ascending or descending", + "block": true + }, + "name": { + "kind": "Name", + "value": "OrderDirection" + }, + "values": [ + { + "kind": "EnumValueDefinition", + "name": { + "kind": "Name", + "value": "asc" + }, + "directives": [] + }, + { + "kind": "EnumValueDefinition", + "name": { + "kind": "Name", + "value": "desc" + }, + "directives": [] + } + ], + "directives": [] + }, + { + "kind": "ObjectTypeDefinition", + "name": { + "kind": "Name", + "value": "Query" + }, + "fields": [ + { + "kind": "FieldDefinition", + "name": { + "kind": "Name", + "value": "collateral" + }, + "arguments": [ + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "id" + }, + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "ID" + } + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "description": { + "kind": "StringValue", + "value": "The block at which the query should be executed. Can either be a `{ hash: Bytes }` value containing a block hash, a `{ number: Int }` containing the block number, or a `{ number_gte: Int }` containing the minimum block number. In the case of `number_gte`, the query will be executed on the latest block only if the subgraph has progressed to or past the minimum block number. Defaults to the latest block when omitted.", + "block": true + }, + "name": { + "kind": "Name", + "value": "block" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Block_height" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "description": { + "kind": "StringValue", + "value": "Set to `allow` to receive data even if the subgraph has skipped over errors while syncing.", + "block": true + }, + "name": { + "kind": "Name", + "value": "subgraphError" + }, + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "_SubgraphErrorPolicy_" + } + } + }, + "defaultValue": { + "kind": "EnumValue", + "value": "deny" + }, + "directives": [] + } + ], + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Collateral" + } + }, + "directives": [] + }, + { + "kind": "FieldDefinition", + "name": { + "kind": "Name", + "value": "collaterals" + }, + "arguments": [ + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "skip" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Int" + } + }, + "defaultValue": { + "kind": "IntValue", + "value": "0" + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "first" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Int" + } + }, + "defaultValue": { + "kind": "IntValue", + "value": "100" + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "orderBy" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Collateral_orderBy" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "orderDirection" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "OrderDirection" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "where" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Collateral_filter" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "description": { + "kind": "StringValue", + "value": "The block at which the query should be executed. Can either be a `{ hash: Bytes }` value containing a block hash, a `{ number: Int }` containing the block number, or a `{ number_gte: Int }` containing the minimum block number. In the case of `number_gte`, the query will be executed on the latest block only if the subgraph has progressed to or past the minimum block number. Defaults to the latest block when omitted.", + "block": true + }, + "name": { + "kind": "Name", + "value": "block" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Block_height" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "description": { + "kind": "StringValue", + "value": "Set to `allow` to receive data even if the subgraph has skipped over errors while syncing.", + "block": true + }, + "name": { + "kind": "Name", + "value": "subgraphError" + }, + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "_SubgraphErrorPolicy_" + } + } + }, + "defaultValue": { + "kind": "EnumValue", + "value": "deny" + }, + "directives": [] + } + ], + "type": { + "kind": "NonNullType", + "type": { + "kind": "ListType", + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Collateral" + } + } + } + } + }, + "directives": [] + }, + { + "kind": "FieldDefinition", + "name": { + "kind": "Name", + "value": "token" + }, + "arguments": [ + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "id" + }, + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "ID" + } + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "description": { + "kind": "StringValue", + "value": "The block at which the query should be executed. Can either be a `{ hash: Bytes }` value containing a block hash, a `{ number: Int }` containing the block number, or a `{ number_gte: Int }` containing the minimum block number. In the case of `number_gte`, the query will be executed on the latest block only if the subgraph has progressed to or past the minimum block number. Defaults to the latest block when omitted.", + "block": true + }, + "name": { + "kind": "Name", + "value": "block" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Block_height" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "description": { + "kind": "StringValue", + "value": "Set to `allow` to receive data even if the subgraph has skipped over errors while syncing.", + "block": true + }, + "name": { + "kind": "Name", + "value": "subgraphError" + }, + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "_SubgraphErrorPolicy_" + } + } + }, + "defaultValue": { + "kind": "EnumValue", + "value": "deny" + }, + "directives": [] + } + ], + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Token" + } + }, + "directives": [] + }, + { + "kind": "FieldDefinition", + "name": { + "kind": "Name", + "value": "tokens" + }, + "arguments": [ + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "skip" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Int" + } + }, + "defaultValue": { + "kind": "IntValue", + "value": "0" + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "first" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Int" + } + }, + "defaultValue": { + "kind": "IntValue", + "value": "100" + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "orderBy" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Token_orderBy" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "orderDirection" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "OrderDirection" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "where" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Token_filter" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "description": { + "kind": "StringValue", + "value": "The block at which the query should be executed. Can either be a `{ hash: Bytes }` value containing a block hash, a `{ number: Int }` containing the block number, or a `{ number_gte: Int }` containing the minimum block number. In the case of `number_gte`, the query will be executed on the latest block only if the subgraph has progressed to or past the minimum block number. Defaults to the latest block when omitted.", + "block": true + }, + "name": { + "kind": "Name", + "value": "block" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Block_height" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "description": { + "kind": "StringValue", + "value": "Set to `allow` to receive data even if the subgraph has skipped over errors while syncing.", + "block": true + }, + "name": { + "kind": "Name", + "value": "subgraphError" + }, + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "_SubgraphErrorPolicy_" + } + } + }, + "defaultValue": { + "kind": "EnumValue", + "value": "deny" + }, + "directives": [] + } + ], + "type": { + "kind": "NonNullType", + "type": { + "kind": "ListType", + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Token" + } + } + } + } + }, + "directives": [] + }, + { + "kind": "FieldDefinition", + "name": { + "kind": "Name", + "value": "collateralAddresses" + }, + "arguments": [ + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "id" + }, + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "ID" + } + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "description": { + "kind": "StringValue", + "value": "The block at which the query should be executed. Can either be a `{ hash: Bytes }` value containing a block hash, a `{ number: Int }` containing the block number, or a `{ number_gte: Int }` containing the minimum block number. In the case of `number_gte`, the query will be executed on the latest block only if the subgraph has progressed to or past the minimum block number. Defaults to the latest block when omitted.", + "block": true + }, + "name": { + "kind": "Name", + "value": "block" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Block_height" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "description": { + "kind": "StringValue", + "value": "Set to `allow` to receive data even if the subgraph has skipped over errors while syncing.", + "block": true + }, + "name": { + "kind": "Name", + "value": "subgraphError" + }, + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "_SubgraphErrorPolicy_" + } + } + }, + "defaultValue": { + "kind": "EnumValue", + "value": "deny" + }, + "directives": [] + } + ], + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "CollateralAddresses" + } + }, + "directives": [] + }, + { + "kind": "FieldDefinition", + "name": { + "kind": "Name", + "value": "collateralAddresses_collection" + }, + "arguments": [ + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "skip" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Int" + } + }, + "defaultValue": { + "kind": "IntValue", + "value": "0" + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "first" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Int" + } + }, + "defaultValue": { + "kind": "IntValue", + "value": "100" + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "orderBy" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "CollateralAddresses_orderBy" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "orderDirection" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "OrderDirection" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "where" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "CollateralAddresses_filter" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "description": { + "kind": "StringValue", + "value": "The block at which the query should be executed. Can either be a `{ hash: Bytes }` value containing a block hash, a `{ number: Int }` containing the block number, or a `{ number_gte: Int }` containing the minimum block number. In the case of `number_gte`, the query will be executed on the latest block only if the subgraph has progressed to or past the minimum block number. Defaults to the latest block when omitted.", + "block": true + }, + "name": { + "kind": "Name", + "value": "block" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Block_height" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "description": { + "kind": "StringValue", + "value": "Set to `allow` to receive data even if the subgraph has skipped over errors while syncing.", + "block": true + }, + "name": { + "kind": "Name", + "value": "subgraphError" + }, + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "_SubgraphErrorPolicy_" + } + } + }, + "defaultValue": { + "kind": "EnumValue", + "value": "deny" + }, + "directives": [] + } + ], + "type": { + "kind": "NonNullType", + "type": { + "kind": "ListType", + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "CollateralAddresses" + } + } + } + } + }, + "directives": [] + }, + { + "kind": "FieldDefinition", + "name": { + "kind": "Name", + "value": "interestRateBracket" + }, + "arguments": [ + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "id" + }, + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "ID" + } + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "description": { + "kind": "StringValue", + "value": "The block at which the query should be executed. Can either be a `{ hash: Bytes }` value containing a block hash, a `{ number: Int }` containing the block number, or a `{ number_gte: Int }` containing the minimum block number. In the case of `number_gte`, the query will be executed on the latest block only if the subgraph has progressed to or past the minimum block number. Defaults to the latest block when omitted.", + "block": true + }, + "name": { + "kind": "Name", + "value": "block" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Block_height" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "description": { + "kind": "StringValue", + "value": "Set to `allow` to receive data even if the subgraph has skipped over errors while syncing.", + "block": true + }, + "name": { + "kind": "Name", + "value": "subgraphError" + }, + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "_SubgraphErrorPolicy_" + } + } + }, + "defaultValue": { + "kind": "EnumValue", + "value": "deny" + }, + "directives": [] + } + ], + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "InterestRateBracket" + } + }, + "directives": [] + }, + { + "kind": "FieldDefinition", + "name": { + "kind": "Name", + "value": "interestRateBrackets" + }, + "arguments": [ + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "skip" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Int" + } + }, + "defaultValue": { + "kind": "IntValue", + "value": "0" + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "first" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Int" + } + }, + "defaultValue": { + "kind": "IntValue", + "value": "100" + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "orderBy" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "InterestRateBracket_orderBy" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "orderDirection" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "OrderDirection" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "where" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "InterestRateBracket_filter" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "description": { + "kind": "StringValue", + "value": "The block at which the query should be executed. Can either be a `{ hash: Bytes }` value containing a block hash, a `{ number: Int }` containing the block number, or a `{ number_gte: Int }` containing the minimum block number. In the case of `number_gte`, the query will be executed on the latest block only if the subgraph has progressed to or past the minimum block number. Defaults to the latest block when omitted.", + "block": true + }, + "name": { + "kind": "Name", + "value": "block" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Block_height" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "description": { + "kind": "StringValue", + "value": "Set to `allow` to receive data even if the subgraph has skipped over errors while syncing.", + "block": true + }, + "name": { + "kind": "Name", + "value": "subgraphError" + }, + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "_SubgraphErrorPolicy_" + } + } + }, + "defaultValue": { + "kind": "EnumValue", + "value": "deny" + }, + "directives": [] + } + ], + "type": { + "kind": "NonNullType", + "type": { + "kind": "ListType", + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "InterestRateBracket" + } + } + } + } + }, + "directives": [] + }, + { + "kind": "FieldDefinition", + "name": { + "kind": "Name", + "value": "trove" + }, + "arguments": [ + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "id" + }, + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "ID" + } + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "description": { + "kind": "StringValue", + "value": "The block at which the query should be executed. Can either be a `{ hash: Bytes }` value containing a block hash, a `{ number: Int }` containing the block number, or a `{ number_gte: Int }` containing the minimum block number. In the case of `number_gte`, the query will be executed on the latest block only if the subgraph has progressed to or past the minimum block number. Defaults to the latest block when omitted.", + "block": true + }, + "name": { + "kind": "Name", + "value": "block" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Block_height" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "description": { + "kind": "StringValue", + "value": "Set to `allow` to receive data even if the subgraph has skipped over errors while syncing.", + "block": true + }, + "name": { + "kind": "Name", + "value": "subgraphError" + }, + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "_SubgraphErrorPolicy_" + } + } + }, + "defaultValue": { + "kind": "EnumValue", + "value": "deny" + }, + "directives": [] + } + ], + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Trove" + } + }, + "directives": [] + }, + { + "kind": "FieldDefinition", + "name": { + "kind": "Name", + "value": "troves" + }, + "arguments": [ + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "skip" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Int" + } + }, + "defaultValue": { + "kind": "IntValue", + "value": "0" + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "first" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Int" + } + }, + "defaultValue": { + "kind": "IntValue", + "value": "100" + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "orderBy" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Trove_orderBy" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "orderDirection" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "OrderDirection" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "where" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Trove_filter" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "description": { + "kind": "StringValue", + "value": "The block at which the query should be executed. Can either be a `{ hash: Bytes }` value containing a block hash, a `{ number: Int }` containing the block number, or a `{ number_gte: Int }` containing the minimum block number. In the case of `number_gte`, the query will be executed on the latest block only if the subgraph has progressed to or past the minimum block number. Defaults to the latest block when omitted.", + "block": true + }, + "name": { + "kind": "Name", + "value": "block" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Block_height" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "description": { + "kind": "StringValue", + "value": "Set to `allow` to receive data even if the subgraph has skipped over errors while syncing.", + "block": true + }, + "name": { + "kind": "Name", + "value": "subgraphError" + }, + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "_SubgraphErrorPolicy_" + } + } + }, + "defaultValue": { + "kind": "EnumValue", + "value": "deny" + }, + "directives": [] + } + ], + "type": { + "kind": "NonNullType", + "type": { + "kind": "ListType", + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Trove" + } + } + } + } + }, + "directives": [] + }, + { + "kind": "FieldDefinition", + "name": { + "kind": "Name", + "value": "borrowerInfo" + }, + "arguments": [ + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "id" + }, + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "ID" + } + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "description": { + "kind": "StringValue", + "value": "The block at which the query should be executed. Can either be a `{ hash: Bytes }` value containing a block hash, a `{ number: Int }` containing the block number, or a `{ number_gte: Int }` containing the minimum block number. In the case of `number_gte`, the query will be executed on the latest block only if the subgraph has progressed to or past the minimum block number. Defaults to the latest block when omitted.", + "block": true + }, + "name": { + "kind": "Name", + "value": "block" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Block_height" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "description": { + "kind": "StringValue", + "value": "Set to `allow` to receive data even if the subgraph has skipped over errors while syncing.", + "block": true + }, + "name": { + "kind": "Name", + "value": "subgraphError" + }, + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "_SubgraphErrorPolicy_" + } + } + }, + "defaultValue": { + "kind": "EnumValue", + "value": "deny" + }, + "directives": [] + } + ], + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "BorrowerInfo" + } + }, + "directives": [] + }, + { + "kind": "FieldDefinition", + "name": { + "kind": "Name", + "value": "borrowerInfos" + }, + "arguments": [ + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "skip" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Int" + } + }, + "defaultValue": { + "kind": "IntValue", + "value": "0" + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "first" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Int" + } + }, + "defaultValue": { + "kind": "IntValue", + "value": "100" + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "orderBy" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "BorrowerInfo_orderBy" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "orderDirection" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "OrderDirection" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "where" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "BorrowerInfo_filter" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "description": { + "kind": "StringValue", + "value": "The block at which the query should be executed. Can either be a `{ hash: Bytes }` value containing a block hash, a `{ number: Int }` containing the block number, or a `{ number_gte: Int }` containing the minimum block number. In the case of `number_gte`, the query will be executed on the latest block only if the subgraph has progressed to or past the minimum block number. Defaults to the latest block when omitted.", + "block": true + }, + "name": { + "kind": "Name", + "value": "block" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Block_height" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "description": { + "kind": "StringValue", + "value": "Set to `allow` to receive data even if the subgraph has skipped over errors while syncing.", + "block": true + }, + "name": { + "kind": "Name", + "value": "subgraphError" + }, + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "_SubgraphErrorPolicy_" + } + } + }, + "defaultValue": { + "kind": "EnumValue", + "value": "deny" + }, + "directives": [] + } + ], + "type": { + "kind": "NonNullType", + "type": { + "kind": "ListType", + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "BorrowerInfo" + } + } + } + } + }, + "directives": [] + }, + { + "kind": "FieldDefinition", + "description": { + "kind": "StringValue", + "value": "Access to subgraph metadata", + "block": true + }, + "name": { + "kind": "Name", + "value": "_meta" + }, + "arguments": [ + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "block" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Block_height" + } + }, + "directives": [] + } + ], + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "_Meta_" + } + }, + "directives": [] + } + ], + "interfaces": [], + "directives": [] + }, + { + "kind": "ObjectTypeDefinition", + "name": { + "kind": "Name", + "value": "Subscription" + }, + "fields": [ + { + "kind": "FieldDefinition", + "name": { + "kind": "Name", + "value": "collateral" + }, + "arguments": [ + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "id" + }, + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "ID" + } + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "description": { + "kind": "StringValue", + "value": "The block at which the query should be executed. Can either be a `{ hash: Bytes }` value containing a block hash, a `{ number: Int }` containing the block number, or a `{ number_gte: Int }` containing the minimum block number. In the case of `number_gte`, the query will be executed on the latest block only if the subgraph has progressed to or past the minimum block number. Defaults to the latest block when omitted.", + "block": true + }, + "name": { + "kind": "Name", + "value": "block" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Block_height" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "description": { + "kind": "StringValue", + "value": "Set to `allow` to receive data even if the subgraph has skipped over errors while syncing.", + "block": true + }, + "name": { + "kind": "Name", + "value": "subgraphError" + }, + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "_SubgraphErrorPolicy_" + } + } + }, + "defaultValue": { + "kind": "EnumValue", + "value": "deny" + }, + "directives": [] + } + ], + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Collateral" + } + }, + "directives": [] + }, + { + "kind": "FieldDefinition", + "name": { + "kind": "Name", + "value": "collaterals" + }, + "arguments": [ + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "skip" + }, "type": { "kind": "NamedType", "name": { @@ -4517,7 +6486,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "Token_orderBy" + "value": "Collateral_orderBy" } }, "directives": [] @@ -4547,7 +6516,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "Token_filter" + "value": "Collateral_filter" } }, "directives": [] @@ -4610,7 +6579,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "Token" + "value": "Collateral" } } } @@ -4622,7 +6591,7 @@ const schemaAST = { "kind": "FieldDefinition", "name": { "kind": "Name", - "value": "collateralAddresses" + "value": "token" }, "arguments": [ { @@ -4695,7 +6664,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "CollateralAddresses" + "value": "Token" } }, "directives": [] @@ -4704,7 +6673,7 @@ const schemaAST = { "kind": "FieldDefinition", "name": { "kind": "Name", - "value": "collateralAddresses_collection" + "value": "tokens" }, "arguments": [ { @@ -4755,7 +6724,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "CollateralAddresses_orderBy" + "value": "Token_orderBy" } }, "directives": [] @@ -4785,7 +6754,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "CollateralAddresses_filter" + "value": "Token_filter" } }, "directives": [] @@ -4848,7 +6817,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "CollateralAddresses" + "value": "Token" } } } @@ -4860,7 +6829,7 @@ const schemaAST = { "kind": "FieldDefinition", "name": { "kind": "Name", - "value": "interestRateBracket" + "value": "collateralAddresses" }, "arguments": [ { @@ -4933,7 +6902,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "InterestRateBracket" + "value": "CollateralAddresses" } }, "directives": [] @@ -4942,7 +6911,7 @@ const schemaAST = { "kind": "FieldDefinition", "name": { "kind": "Name", - "value": "interestRateBrackets" + "value": "collateralAddresses_collection" }, "arguments": [ { @@ -4993,7 +6962,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "InterestRateBracket_orderBy" + "value": "CollateralAddresses_orderBy" } }, "directives": [] @@ -5023,7 +6992,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "InterestRateBracket_filter" + "value": "CollateralAddresses_filter" } }, "directives": [] @@ -5086,7 +7055,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "InterestRateBracket" + "value": "CollateralAddresses" } } } @@ -5098,7 +7067,7 @@ const schemaAST = { "kind": "FieldDefinition", "name": { "kind": "Name", - "value": "trove" + "value": "interestRateBracket" }, "arguments": [ { @@ -5171,7 +7140,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "Trove" + "value": "InterestRateBracket" } }, "directives": [] @@ -5180,7 +7149,7 @@ const schemaAST = { "kind": "FieldDefinition", "name": { "kind": "Name", - "value": "troves" + "value": "interestRateBrackets" }, "arguments": [ { @@ -5231,7 +7200,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "Trove_orderBy" + "value": "InterestRateBracket_orderBy" } }, "directives": [] @@ -5261,7 +7230,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "Trove_filter" + "value": "InterestRateBracket_filter" } }, "directives": [] @@ -5304,87 +7273,39 @@ const schemaAST = { "name": { "kind": "Name", "value": "_SubgraphErrorPolicy_" - } - } - }, - "defaultValue": { - "kind": "EnumValue", - "value": "deny" - }, - "directives": [] - } - ], - "type": { - "kind": "NonNullType", - "type": { - "kind": "ListType", - "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Trove" - } - } - } - } - }, - "directives": [] - }, - { - "kind": "FieldDefinition", - "description": { - "kind": "StringValue", - "value": "Access to subgraph metadata", - "block": true - }, - "name": { - "kind": "Name", - "value": "_meta" - }, - "arguments": [ - { - "kind": "InputValueDefinition", - "name": { - "kind": "Name", - "value": "block" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Block_height" + } } }, + "defaultValue": { + "kind": "EnumValue", + "value": "deny" + }, "directives": [] } ], "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "_Meta_" + "kind": "NonNullType", + "type": { + "kind": "ListType", + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "InterestRateBracket" + } + } + } } }, "directives": [] - } - ], - "interfaces": [], - "directives": [] - }, - { - "kind": "ObjectTypeDefinition", - "name": { - "kind": "Name", - "value": "Subscription" - }, - "fields": [ + }, { "kind": "FieldDefinition", "name": { "kind": "Name", - "value": "collateral" + "value": "trove" }, "arguments": [ { @@ -5457,7 +7378,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "Collateral" + "value": "Trove" } }, "directives": [] @@ -5466,7 +7387,7 @@ const schemaAST = { "kind": "FieldDefinition", "name": { "kind": "Name", - "value": "collaterals" + "value": "troves" }, "arguments": [ { @@ -5517,7 +7438,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "Collateral_orderBy" + "value": "Trove_orderBy" } }, "directives": [] @@ -5547,7 +7468,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "Collateral_filter" + "value": "Trove_filter" } }, "directives": [] @@ -5610,7 +7531,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "Collateral" + "value": "Trove" } } } @@ -5622,7 +7543,7 @@ const schemaAST = { "kind": "FieldDefinition", "name": { "kind": "Name", - "value": "token" + "value": "borrowerInfo" }, "arguments": [ { @@ -5695,7 +7616,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "Token" + "value": "BorrowerInfo" } }, "directives": [] @@ -5704,7 +7625,7 @@ const schemaAST = { "kind": "FieldDefinition", "name": { "kind": "Name", - "value": "tokens" + "value": "borrowerInfos" }, "arguments": [ { @@ -5755,7 +7676,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "Token_orderBy" + "value": "BorrowerInfo_orderBy" } }, "directives": [] @@ -5785,7 +7706,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "Token_filter" + "value": "BorrowerInfo_filter" } }, "directives": [] @@ -5848,7 +7769,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "Token" + "value": "BorrowerInfo" } } } @@ -5857,237 +7778,277 @@ const schemaAST = { "directives": [] }, { - "kind": "FieldDefinition", + "kind": "FieldDefinition", + "description": { + "kind": "StringValue", + "value": "Access to subgraph metadata", + "block": true + }, + "name": { + "kind": "Name", + "value": "_meta" + }, + "arguments": [ + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "block" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Block_height" + } + }, + "directives": [] + } + ], + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "_Meta_" + } + }, + "directives": [] + } + ], + "interfaces": [], + "directives": [] + }, + { + "kind": "ScalarTypeDefinition", + "description": { + "kind": "StringValue", + "value": "A string representation of microseconds UNIX timestamp (16 digits)\n", + "block": true + }, + "name": { + "kind": "Name", + "value": "Timestamp" + }, + "directives": [] + }, + { + "kind": "ObjectTypeDefinition", + "name": { + "kind": "Name", + "value": "Token" + }, + "fields": [ + { + "kind": "FieldDefinition", + "name": { + "kind": "Name", + "value": "id" + }, + "arguments": [], + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "ID" + } + } + }, + "directives": [] + }, + { + "kind": "FieldDefinition", + "name": { + "kind": "Name", + "value": "collateral" + }, + "arguments": [], + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Collateral" + } + } + }, + "directives": [] + }, + { + "kind": "FieldDefinition", + "name": { + "kind": "Name", + "value": "name" + }, + "arguments": [], + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" + } + } + }, + "directives": [] + }, + { + "kind": "FieldDefinition", + "name": { + "kind": "Name", + "value": "symbol" + }, + "arguments": [], + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" + } + } + }, + "directives": [] + }, + { + "kind": "FieldDefinition", + "name": { + "kind": "Name", + "value": "decimals" + }, + "arguments": [], + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Int" + } + } + }, + "directives": [] + } + ], + "interfaces": [], + "directives": [] + }, + { + "kind": "InputObjectTypeDefinition", + "name": { + "kind": "Name", + "value": "Token_filter" + }, + "fields": [ + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "id" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "ID" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "id_not" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "ID" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "id_gt" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "ID" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "collateralAddresses" + "value": "id_lt" }, - "arguments": [ - { - "kind": "InputValueDefinition", - "name": { - "kind": "Name", - "value": "id" - }, - "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "ID" - } - } - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "description": { - "kind": "StringValue", - "value": "The block at which the query should be executed. Can either be a `{ hash: Bytes }` value containing a block hash, a `{ number: Int }` containing the block number, or a `{ number_gte: Int }` containing the minimum block number. In the case of `number_gte`, the query will be executed on the latest block only if the subgraph has progressed to or past the minimum block number. Defaults to the latest block when omitted.", - "block": true - }, - "name": { - "kind": "Name", - "value": "block" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Block_height" - } - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "description": { - "kind": "StringValue", - "value": "Set to `allow` to receive data even if the subgraph has skipped over errors while syncing.", - "block": true - }, - "name": { - "kind": "Name", - "value": "subgraphError" - }, - "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "_SubgraphErrorPolicy_" - } - } - }, - "defaultValue": { - "kind": "EnumValue", - "value": "deny" - }, - "directives": [] + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "ID" } - ], + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "id_gte" + }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "CollateralAddresses" + "value": "ID" } }, "directives": [] }, { - "kind": "FieldDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "collateralAddresses_collection" + "value": "id_lte" }, - "arguments": [ - { - "kind": "InputValueDefinition", - "name": { - "kind": "Name", - "value": "skip" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Int" - } - }, - "defaultValue": { - "kind": "IntValue", - "value": "0" - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "name": { - "kind": "Name", - "value": "first" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Int" - } - }, - "defaultValue": { - "kind": "IntValue", - "value": "100" - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "name": { - "kind": "Name", - "value": "orderBy" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "CollateralAddresses_orderBy" - } - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "name": { - "kind": "Name", - "value": "orderDirection" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "OrderDirection" - } - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "name": { - "kind": "Name", - "value": "where" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "CollateralAddresses_filter" - } - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "description": { - "kind": "StringValue", - "value": "The block at which the query should be executed. Can either be a `{ hash: Bytes }` value containing a block hash, a `{ number: Int }` containing the block number, or a `{ number_gte: Int }` containing the minimum block number. In the case of `number_gte`, the query will be executed on the latest block only if the subgraph has progressed to or past the minimum block number. Defaults to the latest block when omitted.", - "block": true - }, - "name": { - "kind": "Name", - "value": "block" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Block_height" - } - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "description": { - "kind": "StringValue", - "value": "Set to `allow` to receive data even if the subgraph has skipped over errors while syncing.", - "block": true - }, - "name": { - "kind": "Name", - "value": "subgraphError" - }, - "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "_SubgraphErrorPolicy_" - } - } - }, - "defaultValue": { - "kind": "EnumValue", - "value": "deny" - }, - "directives": [] + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "ID" } - ], + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "id_in" + }, "type": { - "kind": "NonNullType", + "kind": "ListType", "type": { - "kind": "ListType", - "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "CollateralAddresses" - } + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "ID" } } } @@ -6095,475 +8056,131 @@ const schemaAST = { "directives": [] }, { - "kind": "FieldDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "interestRateBracket" + "value": "id_not_in" }, - "arguments": [ - { - "kind": "InputValueDefinition", - "name": { - "kind": "Name", - "value": "id" - }, - "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "ID" - } - } - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "description": { - "kind": "StringValue", - "value": "The block at which the query should be executed. Can either be a `{ hash: Bytes }` value containing a block hash, a `{ number: Int }` containing the block number, or a `{ number_gte: Int }` containing the minimum block number. In the case of `number_gte`, the query will be executed on the latest block only if the subgraph has progressed to or past the minimum block number. Defaults to the latest block when omitted.", - "block": true - }, - "name": { - "kind": "Name", - "value": "block" - }, + "type": { + "kind": "ListType", + "type": { + "kind": "NonNullType", "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "Block_height" - } - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "description": { - "kind": "StringValue", - "value": "Set to `allow` to receive data even if the subgraph has skipped over errors while syncing.", - "block": true - }, - "name": { - "kind": "Name", - "value": "subgraphError" - }, - "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "_SubgraphErrorPolicy_" - } + "value": "ID" } - }, - "defaultValue": { - "kind": "EnumValue", - "value": "deny" - }, - "directives": [] + } } - ], + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "collateral" + }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "InterestRateBracket" + "value": "String" } }, "directives": [] }, { - "kind": "FieldDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "interestRateBrackets" + "value": "collateral_not" }, - "arguments": [ - { - "kind": "InputValueDefinition", - "name": { - "kind": "Name", - "value": "skip" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Int" - } - }, - "defaultValue": { - "kind": "IntValue", - "value": "0" - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "name": { - "kind": "Name", - "value": "first" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Int" - } - }, - "defaultValue": { - "kind": "IntValue", - "value": "100" - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "name": { - "kind": "Name", - "value": "orderBy" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "InterestRateBracket_orderBy" - } - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "name": { - "kind": "Name", - "value": "orderDirection" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "OrderDirection" - } - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "name": { - "kind": "Name", - "value": "where" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "InterestRateBracket_filter" - } - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "description": { - "kind": "StringValue", - "value": "The block at which the query should be executed. Can either be a `{ hash: Bytes }` value containing a block hash, a `{ number: Int }` containing the block number, or a `{ number_gte: Int }` containing the minimum block number. In the case of `number_gte`, the query will be executed on the latest block only if the subgraph has progressed to or past the minimum block number. Defaults to the latest block when omitted.", - "block": true - }, - "name": { - "kind": "Name", - "value": "block" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Block_height" - } - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "description": { - "kind": "StringValue", - "value": "Set to `allow` to receive data even if the subgraph has skipped over errors while syncing.", - "block": true - }, - "name": { - "kind": "Name", - "value": "subgraphError" - }, - "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "_SubgraphErrorPolicy_" - } - } - }, - "defaultValue": { - "kind": "EnumValue", - "value": "deny" - }, - "directives": [] + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "collateral_gt" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" + } + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "collateral_lt" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" } - ], + }, + "directives": [] + }, + { + "kind": "InputValueDefinition", + "name": { + "kind": "Name", + "value": "collateral_gte" + }, "type": { - "kind": "NonNullType", - "type": { - "kind": "ListType", - "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "InterestRateBracket" - } - } - } + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" } }, "directives": [] }, { - "kind": "FieldDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "trove" + "value": "collateral_lte" }, - "arguments": [ - { - "kind": "InputValueDefinition", - "name": { - "kind": "Name", - "value": "id" - }, - "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "ID" - } - } - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "description": { - "kind": "StringValue", - "value": "The block at which the query should be executed. Can either be a `{ hash: Bytes }` value containing a block hash, a `{ number: Int }` containing the block number, or a `{ number_gte: Int }` containing the minimum block number. In the case of `number_gte`, the query will be executed on the latest block only if the subgraph has progressed to or past the minimum block number. Defaults to the latest block when omitted.", - "block": true - }, - "name": { - "kind": "Name", - "value": "block" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Block_height" - } - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "description": { - "kind": "StringValue", - "value": "Set to `allow` to receive data even if the subgraph has skipped over errors while syncing.", - "block": true - }, - "name": { - "kind": "Name", - "value": "subgraphError" - }, - "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "_SubgraphErrorPolicy_" - } - } - }, - "defaultValue": { - "kind": "EnumValue", - "value": "deny" - }, - "directives": [] - } - ], "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "Trove" + "value": "String" } }, "directives": [] }, { - "kind": "FieldDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "troves" + "value": "collateral_in" }, - "arguments": [ - { - "kind": "InputValueDefinition", - "name": { - "kind": "Name", - "value": "skip" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Int" - } - }, - "defaultValue": { - "kind": "IntValue", - "value": "0" - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "name": { - "kind": "Name", - "value": "first" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Int" - } - }, - "defaultValue": { - "kind": "IntValue", - "value": "100" - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "name": { - "kind": "Name", - "value": "orderBy" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Trove_orderBy" - } - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "name": { - "kind": "Name", - "value": "orderDirection" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "OrderDirection" - } - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "name": { - "kind": "Name", - "value": "where" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Trove_filter" - } - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "description": { - "kind": "StringValue", - "value": "The block at which the query should be executed. Can either be a `{ hash: Bytes }` value containing a block hash, a `{ number: Int }` containing the block number, or a `{ number_gte: Int }` containing the minimum block number. In the case of `number_gte`, the query will be executed on the latest block only if the subgraph has progressed to or past the minimum block number. Defaults to the latest block when omitted.", - "block": true - }, - "name": { - "kind": "Name", - "value": "block" - }, + "type": { + "kind": "ListType", + "type": { + "kind": "NonNullType", "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "Block_height" - } - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "description": { - "kind": "StringValue", - "value": "Set to `allow` to receive data even if the subgraph has skipped over errors while syncing.", - "block": true - }, - "name": { - "kind": "Name", - "value": "subgraphError" - }, - "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "_SubgraphErrorPolicy_" - } - } - }, - "defaultValue": { - "kind": "EnumValue", - "value": "deny" - }, - "directives": [] - } - ], - "type": { - "kind": "NonNullType", - "type": { - "kind": "ListType", - "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Trove" - } + "value": "String" } } } @@ -6571,183 +8188,112 @@ const schemaAST = { "directives": [] }, { - "kind": "FieldDefinition", - "description": { - "kind": "StringValue", - "value": "Access to subgraph metadata", - "block": true - }, + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "_meta" + "value": "collateral_not_in" }, - "arguments": [ - { - "kind": "InputValueDefinition", - "name": { - "kind": "Name", - "value": "block" - }, + "type": { + "kind": "ListType", + "type": { + "kind": "NonNullType", "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "Block_height" + "value": "String" } - }, - "directives": [] - } - ], - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "_Meta_" + } } }, "directives": [] - } - ], - "interfaces": [], - "directives": [] - }, - { - "kind": "ScalarTypeDefinition", - "description": { - "kind": "StringValue", - "value": "A string representation of microseconds UNIX timestamp (16 digits)\n", - "block": true - }, - "name": { - "kind": "Name", - "value": "Timestamp" - }, - "directives": [] - }, - { - "kind": "ObjectTypeDefinition", - "name": { - "kind": "Name", - "value": "Token" - }, - "fields": [ + }, { - "kind": "FieldDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id" + "value": "collateral_contains" }, - "arguments": [], "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "ID" - } + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" } }, "directives": [] }, { - "kind": "FieldDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "collateral" + "value": "collateral_contains_nocase" }, - "arguments": [], "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Collateral" - } + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" } }, "directives": [] }, { - "kind": "FieldDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "name" + "value": "collateral_not_contains" }, - "arguments": [], "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "String" - } + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" } }, "directives": [] }, { - "kind": "FieldDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "symbol" + "value": "collateral_not_contains_nocase" }, - "arguments": [], "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "String" - } + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" } }, "directives": [] }, { - "kind": "FieldDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "decimals" + "value": "collateral_starts_with" }, - "arguments": [], "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Int" - } + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" } }, "directives": [] - } - ], - "interfaces": [], - "directives": [] - }, - { - "kind": "InputObjectTypeDefinition", - "name": { - "kind": "Name", - "value": "Token_filter" - }, - "fields": [ + }, { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id" + "value": "collateral_starts_with_nocase" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "ID" + "value": "String" } }, "directives": [] @@ -6756,13 +8302,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id_not" + "value": "collateral_not_starts_with" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "ID" + "value": "String" } }, "directives": [] @@ -6771,13 +8317,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id_gt" + "value": "collateral_not_starts_with_nocase" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "ID" + "value": "String" } }, "directives": [] @@ -6786,13 +8332,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id_lt" + "value": "collateral_ends_with" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "ID" + "value": "String" } }, "directives": [] @@ -6801,13 +8347,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id_gte" + "value": "collateral_ends_with_nocase" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "ID" + "value": "String" } }, "directives": [] @@ -6816,13 +8362,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id_lte" + "value": "collateral_not_ends_with" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "ID" + "value": "String" } }, "directives": [] @@ -6831,19 +8377,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id_in" + "value": "collateral_not_ends_with_nocase" }, "type": { - "kind": "ListType", - "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "ID" - } - } + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" } }, "directives": [] @@ -6852,19 +8392,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id_not_in" + "value": "collateral_" }, "type": { - "kind": "ListType", - "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "ID" - } - } + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Collateral_filter" } }, "directives": [] @@ -6873,7 +8407,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "collateral" + "value": "name" }, "type": { "kind": "NamedType", @@ -6888,7 +8422,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "collateral_not" + "value": "name_not" }, "type": { "kind": "NamedType", @@ -6903,7 +8437,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "collateral_gt" + "value": "name_gt" }, "type": { "kind": "NamedType", @@ -6918,7 +8452,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "collateral_lt" + "value": "name_lt" }, "type": { "kind": "NamedType", @@ -6933,7 +8467,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "collateral_gte" + "value": "name_gte" }, "type": { "kind": "NamedType", @@ -6948,7 +8482,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "collateral_lte" + "value": "name_lte" }, "type": { "kind": "NamedType", @@ -6963,7 +8497,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "collateral_in" + "value": "name_in" }, "type": { "kind": "ListType", @@ -6984,7 +8518,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "collateral_not_in" + "value": "name_not_in" }, "type": { "kind": "ListType", @@ -7005,7 +8539,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "collateral_contains" + "value": "name_contains" }, "type": { "kind": "NamedType", @@ -7020,7 +8554,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "collateral_contains_nocase" + "value": "name_contains_nocase" }, "type": { "kind": "NamedType", @@ -7035,7 +8569,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "collateral_not_contains" + "value": "name_not_contains" }, "type": { "kind": "NamedType", @@ -7050,7 +8584,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "collateral_not_contains_nocase" + "value": "name_not_contains_nocase" }, "type": { "kind": "NamedType", @@ -7065,7 +8599,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "collateral_starts_with" + "value": "name_starts_with" }, "type": { "kind": "NamedType", @@ -7080,7 +8614,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "collateral_starts_with_nocase" + "value": "name_starts_with_nocase" }, "type": { "kind": "NamedType", @@ -7095,7 +8629,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "collateral_not_starts_with" + "value": "name_not_starts_with" }, "type": { "kind": "NamedType", @@ -7110,7 +8644,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "collateral_not_starts_with_nocase" + "value": "name_not_starts_with_nocase" }, "type": { "kind": "NamedType", @@ -7125,7 +8659,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "collateral_ends_with" + "value": "name_ends_with" }, "type": { "kind": "NamedType", @@ -7140,7 +8674,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "collateral_ends_with_nocase" + "value": "name_ends_with_nocase" }, "type": { "kind": "NamedType", @@ -7155,7 +8689,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "collateral_not_ends_with" + "value": "name_not_ends_with" }, "type": { "kind": "NamedType", @@ -7170,7 +8704,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "collateral_not_ends_with_nocase" + "value": "name_not_ends_with_nocase" }, "type": { "kind": "NamedType", @@ -7185,22 +8719,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "collateral_" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Collateral_filter" - } - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "name": { - "kind": "Name", - "value": "name" + "value": "symbol" }, "type": { "kind": "NamedType", @@ -7215,7 +8734,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "name_not" + "value": "symbol_not" }, "type": { "kind": "NamedType", @@ -7230,7 +8749,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "name_gt" + "value": "symbol_gt" }, "type": { "kind": "NamedType", @@ -7245,7 +8764,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "name_lt" + "value": "symbol_lt" }, "type": { "kind": "NamedType", @@ -7260,7 +8779,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "name_gte" + "value": "symbol_gte" }, "type": { "kind": "NamedType", @@ -7275,7 +8794,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "name_lte" + "value": "symbol_lte" }, "type": { "kind": "NamedType", @@ -7290,7 +8809,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "name_in" + "value": "symbol_in" }, "type": { "kind": "ListType", @@ -7311,7 +8830,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "name_not_in" + "value": "symbol_not_in" }, "type": { "kind": "ListType", @@ -7332,7 +8851,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "name_contains" + "value": "symbol_contains" }, "type": { "kind": "NamedType", @@ -7347,7 +8866,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "name_contains_nocase" + "value": "symbol_contains_nocase" }, "type": { "kind": "NamedType", @@ -7362,7 +8881,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "name_not_contains" + "value": "symbol_not_contains" }, "type": { "kind": "NamedType", @@ -7377,7 +8896,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "name_not_contains_nocase" + "value": "symbol_not_contains_nocase" }, "type": { "kind": "NamedType", @@ -7392,7 +8911,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "name_starts_with" + "value": "symbol_starts_with" }, "type": { "kind": "NamedType", @@ -7407,7 +8926,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "name_starts_with_nocase" + "value": "symbol_starts_with_nocase" }, "type": { "kind": "NamedType", @@ -7422,7 +8941,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "name_not_starts_with" + "value": "symbol_not_starts_with" }, "type": { "kind": "NamedType", @@ -7437,7 +8956,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "name_not_starts_with_nocase" + "value": "symbol_not_starts_with_nocase" }, "type": { "kind": "NamedType", @@ -7452,7 +8971,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "name_ends_with" + "value": "symbol_ends_with" }, "type": { "kind": "NamedType", @@ -7467,7 +8986,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "name_ends_with_nocase" + "value": "symbol_ends_with_nocase" }, "type": { "kind": "NamedType", @@ -7482,7 +9001,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "name_not_ends_with" + "value": "symbol_not_ends_with" }, "type": { "kind": "NamedType", @@ -7497,7 +9016,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "name_not_ends_with_nocase" + "value": "symbol_not_ends_with_nocase" }, "type": { "kind": "NamedType", @@ -7512,13 +9031,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "symbol" + "value": "decimals" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "String" + "value": "Int" } }, "directives": [] @@ -7527,13 +9046,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "symbol_not" + "value": "decimals_not" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "String" + "value": "Int" } }, "directives": [] @@ -7542,13 +9061,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "symbol_gt" + "value": "decimals_gt" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "String" + "value": "Int" } }, "directives": [] @@ -7557,13 +9076,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "symbol_lt" + "value": "decimals_lt" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "String" + "value": "Int" } }, "directives": [] @@ -7572,13 +9091,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "symbol_gte" + "value": "decimals_gte" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "String" + "value": "Int" } }, "directives": [] @@ -7587,13 +9106,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "symbol_lte" + "value": "decimals_lte" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "String" + "value": "Int" } }, "directives": [] @@ -7602,7 +9121,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "symbol_in" + "value": "decimals_in" }, "type": { "kind": "ListType", @@ -7612,7 +9131,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "String" + "value": "Int" } } } @@ -7623,7 +9142,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "symbol_not_in" + "value": "decimals_not_in" }, "type": { "kind": "ListType", @@ -7633,7 +9152,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "String" + "value": "Int" } } } @@ -7642,15 +9161,20 @@ const schemaAST = { }, { "kind": "InputValueDefinition", + "description": { + "kind": "StringValue", + "value": "Filter for the block changed event.", + "block": true + }, "name": { "kind": "Name", - "value": "symbol_contains" + "value": "_change_block" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "String" + "value": "BlockChangedFilter" } }, "directives": [] @@ -7659,13 +9183,16 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "symbol_contains_nocase" + "value": "and" }, "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "String" + "kind": "ListType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Token_filter" + } } }, "directives": [] @@ -7674,163 +9201,329 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "symbol_not_contains" + "value": "or" }, "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "String" + "kind": "ListType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Token_filter" + } } }, "directives": [] + } + ], + "directives": [] + }, + { + "kind": "EnumTypeDefinition", + "name": { + "kind": "Name", + "value": "Token_orderBy" + }, + "values": [ + { + "kind": "EnumValueDefinition", + "name": { + "kind": "Name", + "value": "id" + }, + "directives": [] }, { - "kind": "InputValueDefinition", + "kind": "EnumValueDefinition", "name": { "kind": "Name", - "value": "symbol_not_contains_nocase" + "value": "collateral" }, + "directives": [] + }, + { + "kind": "EnumValueDefinition", + "name": { + "kind": "Name", + "value": "collateral__id" + }, + "directives": [] + }, + { + "kind": "EnumValueDefinition", + "name": { + "kind": "Name", + "value": "collateral__collIndex" + }, + "directives": [] + }, + { + "kind": "EnumValueDefinition", + "name": { + "kind": "Name", + "value": "collateral__minCollRatio" + }, + "directives": [] + }, + { + "kind": "EnumValueDefinition", + "name": { + "kind": "Name", + "value": "collateral__totalDeposited" + }, + "directives": [] + }, + { + "kind": "EnumValueDefinition", + "name": { + "kind": "Name", + "value": "collateral__totalDebt" + }, + "directives": [] + }, + { + "kind": "EnumValueDefinition", + "name": { + "kind": "Name", + "value": "name" + }, + "directives": [] + }, + { + "kind": "EnumValueDefinition", + "name": { + "kind": "Name", + "value": "symbol" + }, + "directives": [] + }, + { + "kind": "EnumValueDefinition", + "name": { + "kind": "Name", + "value": "decimals" + }, + "directives": [] + } + ], + "directives": [] + }, + { + "kind": "ObjectTypeDefinition", + "name": { + "kind": "Name", + "value": "Trove" + }, + "fields": [ + { + "kind": "FieldDefinition", + "name": { + "kind": "Name", + "value": "id" + }, + "arguments": [], "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "String" + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "ID" + } } }, "directives": [] }, { - "kind": "InputValueDefinition", + "kind": "FieldDefinition", "name": { "kind": "Name", - "value": "symbol_starts_with" + "value": "troveId" }, + "arguments": [], "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "String" + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" + } } }, "directives": [] }, { - "kind": "InputValueDefinition", + "kind": "FieldDefinition", + "name": { + "kind": "Name", + "value": "borrower" + }, + "arguments": [], + "type": { + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Bytes" + } + } + }, + "directives": [] + }, + { + "kind": "FieldDefinition", "name": { "kind": "Name", - "value": "symbol_starts_with_nocase" + "value": "debt" }, + "arguments": [], "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "String" + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "BigInt" + } } }, "directives": [] }, { - "kind": "InputValueDefinition", + "kind": "FieldDefinition", "name": { "kind": "Name", - "value": "symbol_not_starts_with" + "value": "deposit" }, + "arguments": [], "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "String" + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "BigInt" + } } }, "directives": [] }, { - "kind": "InputValueDefinition", + "kind": "FieldDefinition", "name": { "kind": "Name", - "value": "symbol_not_starts_with_nocase" + "value": "stake" }, + "arguments": [], "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "String" + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "BigInt" + } } }, "directives": [] }, { - "kind": "InputValueDefinition", + "kind": "FieldDefinition", "name": { "kind": "Name", - "value": "symbol_ends_with" + "value": "interestRate" }, + "arguments": [], "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "String" + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "BigInt" + } } }, "directives": [] }, { - "kind": "InputValueDefinition", + "kind": "FieldDefinition", "name": { "kind": "Name", - "value": "symbol_ends_with_nocase" + "value": "createdAt" }, + "arguments": [], "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "String" + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "BigInt" + } } }, "directives": [] }, { - "kind": "InputValueDefinition", + "kind": "FieldDefinition", "name": { "kind": "Name", - "value": "symbol_not_ends_with" + "value": "closedAt" }, + "arguments": [], "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "String" + "value": "BigInt" } }, "directives": [] }, { - "kind": "InputValueDefinition", + "kind": "FieldDefinition", "name": { "kind": "Name", - "value": "symbol_not_ends_with_nocase" + "value": "collateral" }, + "arguments": [], "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "String" + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "Collateral" + } } }, "directives": [] - }, + } + ], + "interfaces": [], + "directives": [] + }, + { + "kind": "InputObjectTypeDefinition", + "name": { + "kind": "Name", + "value": "Trove_filter" + }, + "fields": [ { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "decimals" + "value": "id" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "Int" + "value": "ID" } }, "directives": [] @@ -7839,13 +9532,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "decimals_not" + "value": "id_not" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "Int" + "value": "ID" } }, "directives": [] @@ -7854,13 +9547,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "decimals_gt" + "value": "id_gt" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "Int" + "value": "ID" } }, "directives": [] @@ -7869,13 +9562,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "decimals_lt" + "value": "id_lt" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "Int" + "value": "ID" } }, "directives": [] @@ -7884,13 +9577,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "decimals_gte" + "value": "id_gte" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "Int" + "value": "ID" } }, "directives": [] @@ -7899,13 +9592,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "decimals_lte" + "value": "id_lte" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "Int" + "value": "ID" } }, "directives": [] @@ -7914,7 +9607,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "decimals_in" + "value": "id_in" }, "type": { "kind": "ListType", @@ -7924,7 +9617,7 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "Int" + "value": "ID" } } } @@ -7935,7 +9628,7 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "decimals_not_in" + "value": "id_not_in" }, "type": { "kind": "ListType", @@ -7945,351 +9638,216 @@ const schemaAST = { "kind": "NamedType", "name": { "kind": "Name", - "value": "Int" - } - } - } - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "description": { - "kind": "StringValue", - "value": "Filter for the block changed event.", - "block": true - }, - "name": { - "kind": "Name", - "value": "_change_block" - }, - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "BlockChangedFilter" - } - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "name": { - "kind": "Name", - "value": "and" - }, - "type": { - "kind": "ListType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Token_filter" - } - } - }, - "directives": [] - }, - { - "kind": "InputValueDefinition", - "name": { - "kind": "Name", - "value": "or" - }, - "type": { - "kind": "ListType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Token_filter" - } - } - }, - "directives": [] - } - ], - "directives": [] - }, - { - "kind": "EnumTypeDefinition", - "name": { - "kind": "Name", - "value": "Token_orderBy" - }, - "values": [ - { - "kind": "EnumValueDefinition", - "name": { - "kind": "Name", - "value": "id" - }, - "directives": [] - }, - { - "kind": "EnumValueDefinition", - "name": { - "kind": "Name", - "value": "collateral" - }, - "directives": [] - }, - { - "kind": "EnumValueDefinition", - "name": { - "kind": "Name", - "value": "collateral__id" - }, - "directives": [] - }, - { - "kind": "EnumValueDefinition", - "name": { - "kind": "Name", - "value": "collateral__minCollRatio" - }, - "directives": [] - }, - { - "kind": "EnumValueDefinition", - "name": { - "kind": "Name", - "value": "collateral__totalDeposited" + "value": "ID" + } + } + } }, "directives": [] }, { - "kind": "EnumValueDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "collateral__totalDebt" + "value": "troveId" }, - "directives": [] - }, - { - "kind": "EnumValueDefinition", - "name": { - "kind": "Name", - "value": "name" + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" + } }, "directives": [] }, { - "kind": "EnumValueDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "symbol" + "value": "troveId_not" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" + } }, "directives": [] }, { - "kind": "EnumValueDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "decimals" + "value": "troveId_gt" + }, + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" + } }, "directives": [] - } - ], - "directives": [] - }, - { - "kind": "ObjectTypeDefinition", - "name": { - "kind": "Name", - "value": "Trove" - }, - "fields": [ + }, { - "kind": "FieldDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id" + "value": "troveId_lt" }, - "arguments": [], "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "ID" - } + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" } }, "directives": [] }, { - "kind": "FieldDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "borrower" + "value": "troveId_gte" }, - "arguments": [], "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Bytes" - } + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" } }, "directives": [] }, { - "kind": "FieldDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "debt" + "value": "troveId_lte" }, - "arguments": [], "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "BigInt" - } + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" } }, "directives": [] }, { - "kind": "FieldDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "deposit" + "value": "troveId_in" }, - "arguments": [], "type": { - "kind": "NonNullType", + "kind": "ListType", "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "BigInt" + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" + } } } }, "directives": [] }, { - "kind": "FieldDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "stake" + "value": "troveId_not_in" }, - "arguments": [], "type": { - "kind": "NonNullType", + "kind": "ListType", "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "BigInt" + "kind": "NonNullType", + "type": { + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" + } } } }, "directives": [] }, { - "kind": "FieldDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "interestRate" + "value": "troveId_contains" }, - "arguments": [], "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "BigInt" - } + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" } }, "directives": [] }, { - "kind": "FieldDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "createdAt" + "value": "troveId_contains_nocase" }, - "arguments": [], "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "BigInt" - } + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" } }, "directives": [] }, { - "kind": "FieldDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "closedAt" + "value": "troveId_not_contains" }, - "arguments": [], "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "BigInt" + "value": "String" } }, "directives": [] }, { - "kind": "FieldDefinition", + "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "collateral" + "value": "troveId_not_contains_nocase" }, - "arguments": [], "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "Collateral" - } + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" } }, "directives": [] - } - ], - "interfaces": [], - "directives": [] - }, - { - "kind": "InputObjectTypeDefinition", - "name": { - "kind": "Name", - "value": "Trove_filter" - }, - "fields": [ + }, { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id" + "value": "troveId_starts_with" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "ID" + "value": "String" } }, "directives": [] @@ -8298,13 +9856,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id_not" + "value": "troveId_starts_with_nocase" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "ID" + "value": "String" } }, "directives": [] @@ -8313,13 +9871,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id_gt" + "value": "troveId_not_starts_with" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "ID" + "value": "String" } }, "directives": [] @@ -8328,13 +9886,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id_lt" + "value": "troveId_not_starts_with_nocase" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "ID" + "value": "String" } }, "directives": [] @@ -8343,13 +9901,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id_gte" + "value": "troveId_ends_with" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "ID" + "value": "String" } }, "directives": [] @@ -8358,13 +9916,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id_lte" + "value": "troveId_ends_with_nocase" }, "type": { "kind": "NamedType", "name": { "kind": "Name", - "value": "ID" + "value": "String" } }, "directives": [] @@ -8373,19 +9931,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id_in" + "value": "troveId_not_ends_with" }, "type": { - "kind": "ListType", - "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "ID" - } - } + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" } }, "directives": [] @@ -8394,19 +9946,13 @@ const schemaAST = { "kind": "InputValueDefinition", "name": { "kind": "Name", - "value": "id_not_in" + "value": "troveId_not_ends_with_nocase" }, "type": { - "kind": "ListType", - "type": { - "kind": "NonNullType", - "type": { - "kind": "NamedType", - "name": { - "kind": "Name", - "value": "ID" - } - } + "kind": "NamedType", + "name": { + "kind": "Name", + "value": "String" } }, "directives": [] @@ -9766,6 +11312,14 @@ const schemaAST = { }, "directives": [] }, + { + "kind": "EnumValueDefinition", + "name": { + "kind": "Name", + "value": "troveId" + }, + "directives": [] + }, { "kind": "EnumValueDefinition", "name": { @@ -9838,6 +11392,14 @@ const schemaAST = { }, "directives": [] }, + { + "kind": "EnumValueDefinition", + "name": { + "kind": "Name", + "value": "collateral__collIndex" + }, + "directives": [] + }, { "kind": "EnumValueDefinition", "name": { diff --git a/frontend/app/.graphclient/sources/liquity2/schema.graphql b/frontend/app/.graphclient/sources/liquity2/schema.graphql index d53c0294..c563e883 100644 --- a/frontend/app/.graphclient/sources/liquity2/schema.graphql +++ b/frontend/app/.graphclient/sources/liquity2/schema.graphql @@ -35,10 +35,52 @@ input Block_height { number_gte: Int } +type BorrowerInfo { + id: ID! + troves: Int! + trovesByCollateral: [Int!]! +} + +input BorrowerInfo_filter { + id: ID + id_not: ID + id_gt: ID + id_lt: ID + id_gte: ID + id_lte: ID + id_in: [ID!] + id_not_in: [ID!] + troves: Int + troves_not: Int + troves_gt: Int + troves_lt: Int + troves_gte: Int + troves_lte: Int + troves_in: [Int!] + troves_not_in: [Int!] + trovesByCollateral: [Int!] + trovesByCollateral_not: [Int!] + trovesByCollateral_contains: [Int!] + trovesByCollateral_contains_nocase: [Int!] + trovesByCollateral_not_contains: [Int!] + trovesByCollateral_not_contains_nocase: [Int!] + """Filter for the block changed event.""" + _change_block: BlockChangedFilter + and: [BorrowerInfo_filter] + or: [BorrowerInfo_filter] +} + +enum BorrowerInfo_orderBy { + id + troves + trovesByCollateral +} + scalar Bytes type Collateral { id: ID! + collIndex: Int! token: Token! minCollRatio: BigInt! troves(skip: Int = 0, first: Int = 100, orderBy: Trove_orderBy, orderDirection: OrderDirection, where: Trove_filter): [Trove!]! @@ -159,6 +201,7 @@ enum CollateralAddresses_orderBy { borrowerOperations collateral collateral__id + collateral__collIndex collateral__minCollRatio collateral__totalDeposited collateral__totalDebt @@ -178,6 +221,14 @@ input Collateral_filter { id_lte: ID id_in: [ID!] id_not_in: [ID!] + collIndex: Int + collIndex_not: Int + collIndex_gt: Int + collIndex_lt: Int + collIndex_gte: Int + collIndex_lte: Int + collIndex_in: [Int!] + collIndex_not_in: [Int!] token: String token_not: String token_gt: String @@ -233,6 +284,7 @@ input Collateral_filter { enum Collateral_orderBy { id + collIndex token token__id token__name @@ -448,6 +500,32 @@ type Query { """ subgraphError: _SubgraphErrorPolicy_! = deny ): [Trove!]! + borrowerInfo( + id: ID! + """ + The block at which the query should be executed. Can either be a `{ hash: Bytes }` value containing a block hash, a `{ number: Int }` containing the block number, or a `{ number_gte: Int }` containing the minimum block number. In the case of `number_gte`, the query will be executed on the latest block only if the subgraph has progressed to or past the minimum block number. Defaults to the latest block when omitted. + """ + block: Block_height + """ + Set to `allow` to receive data even if the subgraph has skipped over errors while syncing. + """ + subgraphError: _SubgraphErrorPolicy_! = deny + ): BorrowerInfo + borrowerInfos( + skip: Int = 0 + first: Int = 100 + orderBy: BorrowerInfo_orderBy + orderDirection: OrderDirection + where: BorrowerInfo_filter + """ + The block at which the query should be executed. Can either be a `{ hash: Bytes }` value containing a block hash, a `{ number: Int }` containing the block number, or a `{ number_gte: Int }` containing the minimum block number. In the case of `number_gte`, the query will be executed on the latest block only if the subgraph has progressed to or past the minimum block number. Defaults to the latest block when omitted. + """ + block: Block_height + """ + Set to `allow` to receive data even if the subgraph has skipped over errors while syncing. + """ + subgraphError: _SubgraphErrorPolicy_! = deny + ): [BorrowerInfo!]! """Access to subgraph metadata""" _meta(block: Block_height): _Meta_ } @@ -583,6 +661,32 @@ type Subscription { """ subgraphError: _SubgraphErrorPolicy_! = deny ): [Trove!]! + borrowerInfo( + id: ID! + """ + The block at which the query should be executed. Can either be a `{ hash: Bytes }` value containing a block hash, a `{ number: Int }` containing the block number, or a `{ number_gte: Int }` containing the minimum block number. In the case of `number_gte`, the query will be executed on the latest block only if the subgraph has progressed to or past the minimum block number. Defaults to the latest block when omitted. + """ + block: Block_height + """ + Set to `allow` to receive data even if the subgraph has skipped over errors while syncing. + """ + subgraphError: _SubgraphErrorPolicy_! = deny + ): BorrowerInfo + borrowerInfos( + skip: Int = 0 + first: Int = 100 + orderBy: BorrowerInfo_orderBy + orderDirection: OrderDirection + where: BorrowerInfo_filter + """ + The block at which the query should be executed. Can either be a `{ hash: Bytes }` value containing a block hash, a `{ number: Int }` containing the block number, or a `{ number_gte: Int }` containing the minimum block number. In the case of `number_gte`, the query will be executed on the latest block only if the subgraph has progressed to or past the minimum block number. Defaults to the latest block when omitted. + """ + block: Block_height + """ + Set to `allow` to receive data even if the subgraph has skipped over errors while syncing. + """ + subgraphError: _SubgraphErrorPolicy_! = deny + ): [BorrowerInfo!]! """Access to subgraph metadata""" _meta(block: Block_height): _Meta_ } @@ -689,6 +793,7 @@ enum Token_orderBy { id collateral collateral__id + collateral__collIndex collateral__minCollRatio collateral__totalDeposited collateral__totalDebt @@ -699,6 +804,7 @@ enum Token_orderBy { type Trove { id: ID! + troveId: String! borrower: Bytes! debt: BigInt! deposit: BigInt! @@ -718,6 +824,26 @@ input Trove_filter { id_lte: ID id_in: [ID!] id_not_in: [ID!] + troveId: String + troveId_not: String + troveId_gt: String + troveId_lt: String + troveId_gte: String + troveId_lte: String + troveId_in: [String!] + troveId_not_in: [String!] + troveId_contains: String + troveId_contains_nocase: String + troveId_not_contains: String + troveId_not_contains_nocase: String + troveId_starts_with: String + troveId_starts_with_nocase: String + troveId_not_starts_with: String + troveId_not_starts_with_nocase: String + troveId_ends_with: String + troveId_ends_with_nocase: String + troveId_not_ends_with: String + troveId_not_ends_with_nocase: String borrower: Bytes borrower_not: Bytes borrower_gt: Bytes @@ -805,6 +931,7 @@ input Trove_filter { enum Trove_orderBy { id + troveId borrower debt deposit @@ -814,6 +941,7 @@ enum Trove_orderBy { closedAt collateral collateral__id + collateral__collIndex collateral__minCollRatio collateral__totalDeposited collateral__totalDebt diff --git a/frontend/app/.graphclient/sources/liquity2/types.ts b/frontend/app/.graphclient/sources/liquity2/types.ts index 4852f8c1..c708275d 100644 --- a/frontend/app/.graphclient/sources/liquity2/types.ts +++ b/frontend/app/.graphclient/sources/liquity2/types.ts @@ -39,8 +39,49 @@ export type Block_height = { readonly number_gte?: InputMaybe; }; +export type BorrowerInfo = { + readonly id: Scalars['ID']['output']; + readonly troves: Scalars['Int']['output']; + readonly trovesByCollateral: ReadonlyArray; +}; + +export type BorrowerInfo_filter = { + readonly id?: InputMaybe; + readonly id_not?: InputMaybe; + readonly id_gt?: InputMaybe; + readonly id_lt?: InputMaybe; + readonly id_gte?: InputMaybe; + readonly id_lte?: InputMaybe; + readonly id_in?: InputMaybe>; + readonly id_not_in?: InputMaybe>; + readonly troves?: InputMaybe; + readonly troves_not?: InputMaybe; + readonly troves_gt?: InputMaybe; + readonly troves_lt?: InputMaybe; + readonly troves_gte?: InputMaybe; + readonly troves_lte?: InputMaybe; + readonly troves_in?: InputMaybe>; + readonly troves_not_in?: InputMaybe>; + readonly trovesByCollateral?: InputMaybe>; + readonly trovesByCollateral_not?: InputMaybe>; + readonly trovesByCollateral_contains?: InputMaybe>; + readonly trovesByCollateral_contains_nocase?: InputMaybe>; + readonly trovesByCollateral_not_contains?: InputMaybe>; + readonly trovesByCollateral_not_contains_nocase?: InputMaybe>; + /** Filter for the block changed event. */ + readonly _change_block?: InputMaybe; + readonly and?: InputMaybe>>; + readonly or?: InputMaybe>>; +}; + +export type BorrowerInfo_orderBy = + | 'id' + | 'troves' + | 'trovesByCollateral'; + export type Collateral = { readonly id: Scalars['ID']['output']; + readonly collIndex: Scalars['Int']['output']; readonly token: Token; readonly minCollRatio: Scalars['BigInt']['output']; readonly troves: ReadonlyArray; @@ -170,6 +211,7 @@ export type CollateralAddresses_orderBy = | 'borrowerOperations' | 'collateral' | 'collateral__id' + | 'collateral__collIndex' | 'collateral__minCollRatio' | 'collateral__totalDeposited' | 'collateral__totalDebt' @@ -188,6 +230,14 @@ export type Collateral_filter = { readonly id_lte?: InputMaybe; readonly id_in?: InputMaybe>; readonly id_not_in?: InputMaybe>; + readonly collIndex?: InputMaybe; + readonly collIndex_not?: InputMaybe; + readonly collIndex_gt?: InputMaybe; + readonly collIndex_lt?: InputMaybe; + readonly collIndex_gte?: InputMaybe; + readonly collIndex_lte?: InputMaybe; + readonly collIndex_in?: InputMaybe>; + readonly collIndex_not_in?: InputMaybe>; readonly token?: InputMaybe; readonly token_not?: InputMaybe; readonly token_gt?: InputMaybe; @@ -243,6 +293,7 @@ export type Collateral_filter = { export type Collateral_orderBy = | 'id' + | 'collIndex' | 'token' | 'token__id' | 'token__name' @@ -329,6 +380,8 @@ export type Query = { readonly interestRateBrackets: ReadonlyArray; readonly trove?: Maybe; readonly troves: ReadonlyArray; + readonly borrowerInfo?: Maybe; + readonly borrowerInfos: ReadonlyArray; /** Access to subgraph metadata */ readonly _meta?: Maybe<_Meta_>; }; @@ -424,6 +477,24 @@ export type QuerytrovesArgs = { }; +export type QueryborrowerInfoArgs = { + id: Scalars['ID']['input']; + block?: InputMaybe; + subgraphError?: _SubgraphErrorPolicy_; +}; + + +export type QueryborrowerInfosArgs = { + skip?: InputMaybe; + first?: InputMaybe; + orderBy?: InputMaybe; + orderDirection?: InputMaybe; + where?: InputMaybe; + block?: InputMaybe; + subgraphError?: _SubgraphErrorPolicy_; +}; + + export type Query_metaArgs = { block?: InputMaybe; }; @@ -439,6 +510,8 @@ export type Subscription = { readonly interestRateBrackets: ReadonlyArray; readonly trove?: Maybe; readonly troves: ReadonlyArray; + readonly borrowerInfo?: Maybe; + readonly borrowerInfos: ReadonlyArray; /** Access to subgraph metadata */ readonly _meta?: Maybe<_Meta_>; }; @@ -534,6 +607,24 @@ export type SubscriptiontrovesArgs = { }; +export type SubscriptionborrowerInfoArgs = { + id: Scalars['ID']['input']; + block?: InputMaybe; + subgraphError?: _SubgraphErrorPolicy_; +}; + + +export type SubscriptionborrowerInfosArgs = { + skip?: InputMaybe; + first?: InputMaybe; + orderBy?: InputMaybe; + orderDirection?: InputMaybe; + where?: InputMaybe; + block?: InputMaybe; + subgraphError?: _SubgraphErrorPolicy_; +}; + + export type Subscription_metaArgs = { block?: InputMaybe; }; @@ -634,6 +725,7 @@ export type Token_orderBy = | 'id' | 'collateral' | 'collateral__id' + | 'collateral__collIndex' | 'collateral__minCollRatio' | 'collateral__totalDeposited' | 'collateral__totalDebt' @@ -643,6 +735,7 @@ export type Token_orderBy = export type Trove = { readonly id: Scalars['ID']['output']; + readonly troveId: Scalars['String']['output']; readonly borrower: Scalars['Bytes']['output']; readonly debt: Scalars['BigInt']['output']; readonly deposit: Scalars['BigInt']['output']; @@ -662,6 +755,26 @@ export type Trove_filter = { readonly id_lte?: InputMaybe; readonly id_in?: InputMaybe>; readonly id_not_in?: InputMaybe>; + readonly troveId?: InputMaybe; + readonly troveId_not?: InputMaybe; + readonly troveId_gt?: InputMaybe; + readonly troveId_lt?: InputMaybe; + readonly troveId_gte?: InputMaybe; + readonly troveId_lte?: InputMaybe; + readonly troveId_in?: InputMaybe>; + readonly troveId_not_in?: InputMaybe>; + readonly troveId_contains?: InputMaybe; + readonly troveId_contains_nocase?: InputMaybe; + readonly troveId_not_contains?: InputMaybe; + readonly troveId_not_contains_nocase?: InputMaybe; + readonly troveId_starts_with?: InputMaybe; + readonly troveId_starts_with_nocase?: InputMaybe; + readonly troveId_not_starts_with?: InputMaybe; + readonly troveId_not_starts_with_nocase?: InputMaybe; + readonly troveId_ends_with?: InputMaybe; + readonly troveId_ends_with_nocase?: InputMaybe; + readonly troveId_not_ends_with?: InputMaybe; + readonly troveId_not_ends_with_nocase?: InputMaybe; readonly borrower?: InputMaybe; readonly borrower_not?: InputMaybe; readonly borrower_gt?: InputMaybe; @@ -749,6 +862,7 @@ export type Trove_filter = { export type Trove_orderBy = | 'id' + | 'troveId' | 'borrower' | 'debt' | 'deposit' @@ -758,6 +872,7 @@ export type Trove_orderBy = | 'closedAt' | 'collateral' | 'collateral__id' + | 'collateral__collIndex' | 'collateral__minCollRatio' | 'collateral__totalDeposited' | 'collateral__totalDebt'; @@ -816,6 +931,10 @@ export type _SubgraphErrorPolicy_ = trove: InContextSdkMethod, /** null **/ troves: InContextSdkMethod, + /** null **/ + borrowerInfo: InContextSdkMethod, + /** null **/ + borrowerInfos: InContextSdkMethod, /** Access to subgraph metadata **/ _meta: InContextSdkMethod }; @@ -845,6 +964,10 @@ export type _SubgraphErrorPolicy_ = trove: InContextSdkMethod, /** null **/ troves: InContextSdkMethod, + /** null **/ + borrowerInfo: InContextSdkMethod, + /** null **/ + borrowerInfos: InContextSdkMethod, /** Access to subgraph metadata **/ _meta: InContextSdkMethod }; diff --git a/frontend/app/.graphclientrc.yml b/frontend/app/.graphclientrc.yml index 77649ff9..e63e40f0 100644 --- a/frontend/app/.graphclientrc.yml +++ b/frontend/app/.graphclientrc.yml @@ -2,7 +2,8 @@ sources: - name: liquity2 handler: graphql: - endpoint: http://localhost:8000/subgraphs/name/liquity2/liquity2 + # endpoint: http://localhost:8000/subgraphs/name/liquity2/liquity2 + endpoint: https://api.studio.thegraph.com/query/42403/liquity2/version/latest codegen: strictScalars: true diff --git a/frontend/app/package.json b/frontend/app/package.json index 399b94c5..4e475ec9 100644 --- a/frontend/app/package.json +++ b/frontend/app/package.json @@ -21,6 +21,7 @@ "@rainbow-me/rainbowkit": "^2.1.3", "@react-spring/web": "^9.7.4", "@tanstack/react-query": "^5.51.16", + "@wagmi/core": "^2.12.2", "dnum": "^2.13.1", "geist": "^1.3.1", "next": "~14.2.5", diff --git a/frontend/app/scripts/update-liquity-abis.ts b/frontend/app/scripts/update-liquity-abis.ts index 0252814d..b2bafaef 100644 --- a/frontend/app/scripts/update-liquity-abis.ts +++ b/frontend/app/scripts/update-liquity-abis.ts @@ -19,6 +19,7 @@ const ABIS = [ ["CollateralRegistry"], ["HintHelpers"], ["MultiTroveGetter"], + ["WETH"], // Collaterals ["ActivePool"], @@ -36,9 +37,8 @@ const ArtifactSchema = v.object({ abi: v.array(v.unknown()), }); -async function writeAbiFromArtifact(artifactPath: string, abiName: string) { - const json = await fs.readFile(artifactPath, "utf-8"); - const artifact = v.parse(ArtifactSchema, JSON.parse(json)); +async function writeAbiFromArtifact(abi: unknown, abiName: string) { + const artifact = v.parse(ArtifactSchema, abi); const tsFileContent = [ "// this file was generated by scripts/update-liquity-abis.ts", @@ -50,6 +50,38 @@ async function writeAbiFromArtifact(artifactPath: string, abiName: string) { await $`dprint --log-level silent fmt ${appAbisDir}/${abiName}.ts`; } +async function getFirstJsonFound(dir: string) { + const files = await fs.readdir(dir); + for (const file of files) { + if (file.endsWith(".json")) { + return `${dir}/${file}`; + } + } + throw new Error(`No JSON files found in ${dir}`); +} + +async function readJsonFromDir(dir: string, names: string[]) { + // try to find the file with the names provided + for (const name of names) { + console.log(`👉 Trying to find ${name}.json in ${dir}/${name}.sol/…`); + try { + return JSON.parse( + await fs.readFile(`${dir}/${name}.sol/${name}.json`, "utf-8"), + ); + } catch (_) {} + } + + // if not found, try the JSON file in the directory + try { + console.log(`👉 Trying to find any JSON file in ${dir}/${names[0]}.sol/…`); + return JSON.parse( + await fs.readFile(await getFirstJsonFound(`${dir}/${names[0]}.sol`), "utf-8"), + ); + } catch (_) {} + + return null; +} + async function main() { console.log("👉 Building Liquity contracts…\n"); await $`forge build --root ${contractsDir} --out ${artifactsTmpDir}`; @@ -58,25 +90,13 @@ async function main() { await Promise.all(ABIS.map(async (possibleNames) => { const abiName = possibleNames[0]; - let foundAbiName: string | null = null; - for (const possibleName of possibleNames) { - try { - await fs.access(`${artifactsTmpDir}/${possibleName}.sol/${possibleName}.json`); - foundAbiName = possibleName; - break; - } catch (_) {} - } + const abi = await readJsonFromDir(`${artifactsTmpDir}`, possibleNames); - if (!foundAbiName) { + if (!abi) { throw new Error(`Could not find ABI for ${possibleNames.join(", ")}`); } - return ( - writeAbiFromArtifact( - `${artifactsTmpDir}/${foundAbiName}.sol/${foundAbiName}.json`, - abiName, - ) - ); + return writeAbiFromArtifact(abi, abiName); })); console.log("👉 Removing temporary artifacts…"); diff --git a/frontend/app/src/abi/ActivePool.ts b/frontend/app/src/abi/ActivePool.ts index 90fb1f7b..a19614d0 100644 --- a/frontend/app/src/abi/ActivePool.ts +++ b/frontend/app/src/abi/ActivePool.ts @@ -3,7 +3,7 @@ export const ActivePool = [ { "type": "constructor", - "inputs": [{ "name": "_collAddress", "type": "address", "internalType": "address" }], + "inputs": [{ "name": "_addressesRegistry", "type": "address", "internalType": "contract IAddressesRegistry" }], "stateMutability": "nonpayable", }, { @@ -20,6 +20,13 @@ export const ActivePool = [ "outputs": [], "stateMutability": "nonpayable", }, + { + "type": "function", + "name": "aggBatchManagementFees", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], + "stateMutability": "view", + }, { "type": "function", "name": "aggRecordedDebt", @@ -27,6 +34,13 @@ export const ActivePool = [ "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], "stateMutability": "view", }, + { + "type": "function", + "name": "aggWeightedBatchManagementFeeSum", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], + "stateMutability": "view", + }, { "type": "function", "name": "aggWeightedDebtSum", @@ -41,6 +55,13 @@ export const ActivePool = [ "outputs": [{ "name": "", "type": "address", "internalType": "address" }], "stateMutability": "view", }, + { + "type": "function", + "name": "calcPendingAggBatchManagementFee", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], + "stateMutability": "view", + }, { "type": "function", "name": "calcPendingAggInterest", @@ -100,6 +121,9 @@ export const ActivePool = [ { "name": "newWeightedRecordedDebt", "type": "uint256", "internalType": "uint256" }, { "name": "oldWeightedRecordedDebt", "type": "uint256", "internalType": "uint256" }, { "name": "upfrontFee", "type": "uint256", "internalType": "uint256" }, + { "name": "batchAccruedManagementFee", "type": "uint256", "internalType": "uint256" }, + { "name": "newWeightedRecordedBatchManagementFee", "type": "uint256", "internalType": "uint256" }, + { "name": "oldWeightedRecordedBatchManagementFee", "type": "uint256", "internalType": "uint256" }, ], }], "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], @@ -121,9 +145,9 @@ export const ActivePool = [ }, { "type": "function", - "name": "isOwner", + "name": "lastAggBatchManagementFeesUpdateTime", "inputs": [], - "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }], + "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], "stateMutability": "view", }, { @@ -151,17 +175,38 @@ export const ActivePool = [ { "name": "newWeightedRecordedDebt", "type": "uint256", "internalType": "uint256" }, { "name": "oldWeightedRecordedDebt", "type": "uint256", "internalType": "uint256" }, { "name": "upfrontFee", "type": "uint256", "internalType": "uint256" }, + { "name": "batchAccruedManagementFee", "type": "uint256", "internalType": "uint256" }, + { "name": "newWeightedRecordedBatchManagementFee", "type": "uint256", "internalType": "uint256" }, + { "name": "oldWeightedRecordedBatchManagementFee", "type": "uint256", "internalType": "uint256" }, ], - }], + }, { "name": "_batchAddress", "type": "address", "internalType": "address" }], "outputs": [], "stateMutability": "nonpayable", }, { "type": "function", - "name": "owner", - "inputs": [], - "outputs": [{ "name": "", "type": "address", "internalType": "address" }], - "stateMutability": "view", + "name": "mintBatchManagementFeeAndAccountForChange", + "inputs": [{ + "name": "_troveChange", + "type": "tuple", + "internalType": "struct TroveChange", + "components": [ + { "name": "appliedRedistBoldDebtGain", "type": "uint256", "internalType": "uint256" }, + { "name": "appliedRedistCollGain", "type": "uint256", "internalType": "uint256" }, + { "name": "collIncrease", "type": "uint256", "internalType": "uint256" }, + { "name": "collDecrease", "type": "uint256", "internalType": "uint256" }, + { "name": "debtIncrease", "type": "uint256", "internalType": "uint256" }, + { "name": "debtDecrease", "type": "uint256", "internalType": "uint256" }, + { "name": "newWeightedRecordedDebt", "type": "uint256", "internalType": "uint256" }, + { "name": "oldWeightedRecordedDebt", "type": "uint256", "internalType": "uint256" }, + { "name": "upfrontFee", "type": "uint256", "internalType": "uint256" }, + { "name": "batchAccruedManagementFee", "type": "uint256", "internalType": "uint256" }, + { "name": "newWeightedRecordedBatchManagementFee", "type": "uint256", "internalType": "uint256" }, + { "name": "oldWeightedRecordedBatchManagementFee", "type": "uint256", "internalType": "uint256" }, + ], + }, { "name": "_batchAddress", "type": "address", "internalType": "address" }], + "outputs": [], + "stateMutability": "nonpayable", }, { "type": "function", @@ -188,21 +233,14 @@ export const ActivePool = [ "outputs": [], "stateMutability": "nonpayable", }, + { "type": "function", "name": "setShutdownFlag", "inputs": [], "outputs": [], "stateMutability": "nonpayable" }, { "type": "function", - "name": "setAddresses", - "inputs": [ - { "name": "_borrowerOperationsAddress", "type": "address", "internalType": "address" }, - { "name": "_troveManagerAddress", "type": "address", "internalType": "address" }, - { "name": "_stabilityPoolAddress", "type": "address", "internalType": "address" }, - { "name": "_defaultPoolAddress", "type": "address", "internalType": "address" }, - { "name": "_boldTokenAddress", "type": "address", "internalType": "address" }, - { "name": "_interestRouterAddress", "type": "address", "internalType": "address" }, - ], - "outputs": [], - "stateMutability": "nonpayable", + "name": "shutdownTime", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], + "stateMutability": "view", }, - { "type": "function", "name": "setShutdownFlag", "inputs": [], "outputs": [], "stateMutability": "nonpayable" }, { "type": "function", "name": "stabilityPool", @@ -240,6 +278,12 @@ export const ActivePool = [ }], "anonymous": false, }, + { + "type": "event", + "name": "CollTokenAddressChanged", + "inputs": [{ "name": "_newCollTokenAddress", "type": "address", "indexed": false, "internalType": "address" }], + "anonymous": false, + }, { "type": "event", "name": "DefaultPoolAddressChanged", @@ -257,17 +301,6 @@ export const ActivePool = [ }], "anonymous": false, }, - { - "type": "event", - "name": "OwnershipTransferred", - "inputs": [{ "name": "previousOwner", "type": "address", "indexed": true, "internalType": "address" }, { - "name": "newOwner", - "type": "address", - "indexed": true, - "internalType": "address", - }], - "anonymous": false, - }, { "type": "event", "name": "StabilityPoolAddressChanged", diff --git a/frontend/app/src/abi/BorrowerOperations.ts b/frontend/app/src/abi/BorrowerOperations.ts index 3e344306..024aeed5 100644 --- a/frontend/app/src/abi/BorrowerOperations.ts +++ b/frontend/app/src/abi/BorrowerOperations.ts @@ -3,11 +3,7 @@ export const BorrowerOperations = [ { "type": "constructor", - "inputs": [{ "name": "_collToken", "type": "address", "internalType": "contract IERC20" }, { - "name": "_troveManager", - "type": "address", - "internalType": "contract ITroveManager", - }, { "name": "_weth", "type": "address", "internalType": "contract IWETH" }], + "inputs": [{ "name": "_addressesRegistry", "type": "address", "internalType": "contract IAddressesRegistry" }], "stateMutability": "nonpayable", }, { @@ -24,13 +20,6 @@ export const BorrowerOperations = [ "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], "stateMutability": "view", }, - { - "type": "function", - "name": "NAME", - "inputs": [], - "outputs": [{ "name": "", "type": "string", "internalType": "string" }], - "stateMutability": "view", - }, { "type": "function", "name": "SCR", @@ -38,13 +27,6 @@ export const BorrowerOperations = [ "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], "stateMutability": "view", }, - { - "type": "function", - "name": "WETH", - "inputs": [], - "outputs": [{ "name": "", "type": "address", "internalType": "contract IWETH" }], - "stateMutability": "view", - }, { "type": "function", "name": "activePool", @@ -115,7 +97,7 @@ export const BorrowerOperations = [ }, { "type": "function", - "name": "applyTroveInterestPermissionless", + "name": "applyPendingDebt", "inputs": [{ "name": "_troveId", "type": "uint256", "internalType": "uint256" }, { "name": "_lowerHint", "type": "uint256", @@ -126,9 +108,9 @@ export const BorrowerOperations = [ }, { "type": "function", - "name": "boldToken", - "inputs": [], - "outputs": [{ "name": "", "type": "address", "internalType": "contract IBoldToken" }], + "name": "checkBatchManagerExists", + "inputs": [{ "name": "_batchManager", "type": "address", "internalType": "address" }], + "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }], "stateMutability": "view", }, { "type": "function", "name": "claimCollateral", "inputs": [], "outputs": [], "stateMutability": "nonpayable" }, @@ -136,35 +118,53 @@ export const BorrowerOperations = [ "type": "function", "name": "closeTrove", "inputs": [{ "name": "_troveId", "type": "uint256", "internalType": "uint256" }], - "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], + "outputs": [], "stateMutability": "nonpayable", }, { "type": "function", - "name": "collToken", + "name": "getEntireSystemColl", "inputs": [], - "outputs": [{ "name": "", "type": "address", "internalType": "contract IERC20" }], + "outputs": [{ "name": "entireSystemColl", "type": "uint256", "internalType": "uint256" }], "stateMutability": "view", }, { "type": "function", - "name": "defaultPool", + "name": "getEntireSystemDebt", "inputs": [], - "outputs": [{ "name": "", "type": "address", "internalType": "contract IDefaultPool" }], + "outputs": [{ "name": "entireSystemDebt", "type": "uint256", "internalType": "uint256" }], "stateMutability": "view", }, { "type": "function", - "name": "getEntireSystemColl", - "inputs": [], - "outputs": [{ "name": "entireSystemColl", "type": "uint256", "internalType": "uint256" }], + "name": "getInterestBatchManager", + "inputs": [{ "name": "_account", "type": "address", "internalType": "address" }], + "outputs": [{ + "name": "", + "type": "tuple", + "internalType": "struct IBorrowerOperations.InterestBatchManager", + "components": [{ "name": "minInterestRate", "type": "uint128", "internalType": "uint128" }, { + "name": "maxInterestRate", + "type": "uint128", + "internalType": "uint128", + }, { "name": "minInterestRateChangePeriod", "type": "uint256", "internalType": "uint256" }], + }], "stateMutability": "view", }, { "type": "function", - "name": "getEntireSystemDebt", - "inputs": [], - "outputs": [{ "name": "entireSystemDebt", "type": "uint256", "internalType": "uint256" }], + "name": "getInterestIndividualDelegateOf", + "inputs": [{ "name": "_troveId", "type": "uint256", "internalType": "uint256" }], + "outputs": [{ + "name": "", + "type": "tuple", + "internalType": "struct IBorrowerOperations.InterestIndividualDelegate", + "components": [{ "name": "account", "type": "address", "internalType": "address" }, { + "name": "minInterestRate", + "type": "uint128", + "internalType": "uint128", + }, { "name": "maxInterestRate", "type": "uint128", "internalType": "uint128" }], + }], "stateMutability": "view", }, { @@ -176,25 +176,23 @@ export const BorrowerOperations = [ }, { "type": "function", - "name": "isOwner", - "inputs": [], - "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }], + "name": "interestBatchManagerOf", + "inputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], + "outputs": [{ "name": "", "type": "address", "internalType": "address" }], "stateMutability": "view", }, { "type": "function", - "name": "openTrove", - "inputs": [ - { "name": "_owner", "type": "address", "internalType": "address" }, - { "name": "_ownerIndex", "type": "uint256", "internalType": "uint256" }, - { "name": "_collAmount", "type": "uint256", "internalType": "uint256" }, - { "name": "_boldAmount", "type": "uint256", "internalType": "uint256" }, - { "name": "_upperHint", "type": "uint256", "internalType": "uint256" }, - { "name": "_lowerHint", "type": "uint256", "internalType": "uint256" }, - { "name": "_annualInterestRate", "type": "uint256", "internalType": "uint256" }, - { "name": "_maxUpfrontFee", "type": "uint256", "internalType": "uint256" }, - ], - "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], + "name": "lowerBatchManagementFee", + "inputs": [{ "name": "_newAnnualManagementFee", "type": "uint256", "internalType": "uint256" }], + "outputs": [], + "stateMutability": "nonpayable", + }, + { + "type": "function", + "name": "onLiquidateTrove", + "inputs": [{ "name": "_troveId", "type": "uint256", "internalType": "uint256" }], + "outputs": [], "stateMutability": "nonpayable", }, { @@ -218,27 +216,70 @@ export const BorrowerOperations = [ }, { "type": "function", - "name": "owner", - "inputs": [], - "outputs": [{ "name": "", "type": "address", "internalType": "address" }], - "stateMutability": "view", + "name": "openTroveAndJoinInterestBatchManager", + "inputs": [{ + "name": "_params", + "type": "tuple", + "internalType": "struct IBorrowerOperations.OpenTroveAndJoinInterestBatchManagerParams", + "components": [ + { "name": "owner", "type": "address", "internalType": "address" }, + { "name": "ownerIndex", "type": "uint256", "internalType": "uint256" }, + { "name": "collAmount", "type": "uint256", "internalType": "uint256" }, + { "name": "boldAmount", "type": "uint256", "internalType": "uint256" }, + { "name": "upperHint", "type": "uint256", "internalType": "uint256" }, + { "name": "lowerHint", "type": "uint256", "internalType": "uint256" }, + { "name": "interestBatchManager", "type": "address", "internalType": "address" }, + { "name": "maxUpfrontFee", "type": "uint256", "internalType": "uint256" }, + { "name": "addManager", "type": "address", "internalType": "address" }, + { "name": "removeManager", "type": "address", "internalType": "address" }, + { "name": "receiver", "type": "address", "internalType": "address" }, + ], + }], + "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], + "stateMutability": "nonpayable", }, { "type": "function", - "name": "priceFeed", - "inputs": [], - "outputs": [{ "name": "", "type": "address", "internalType": "contract IPriceFeed" }], - "stateMutability": "view", + "name": "registerBatchManager", + "inputs": [ + { "name": "_minInterestRate", "type": "uint128", "internalType": "uint128" }, + { "name": "_maxInterestRate", "type": "uint128", "internalType": "uint128" }, + { "name": "_currentInterestRate", "type": "uint128", "internalType": "uint128" }, + { "name": "_annualManagementFee", "type": "uint128", "internalType": "uint128" }, + { "name": "_minInterestRateChangePeriod", "type": "uint128", "internalType": "uint128" }, + ], + "outputs": [], + "stateMutability": "nonpayable", + }, + { + "type": "function", + "name": "removeFromBatch", + "inputs": [ + { "name": "_troveId", "type": "uint256", "internalType": "uint256" }, + { "name": "_newAnnualInterestRate", "type": "uint256", "internalType": "uint256" }, + { "name": "_upperHint", "type": "uint256", "internalType": "uint256" }, + { "name": "_lowerHint", "type": "uint256", "internalType": "uint256" }, + { "name": "_maxUpfrontFee", "type": "uint256", "internalType": "uint256" }, + ], + "outputs": [], + "stateMutability": "nonpayable", + }, + { + "type": "function", + "name": "removeInterestIndividualDelegate", + "inputs": [{ "name": "_troveId", "type": "uint256", "internalType": "uint256" }], + "outputs": [], + "stateMutability": "nonpayable", }, { "type": "function", "name": "removeManagerReceiverOf", - "inputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }, { - "name": "", + "inputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], + "outputs": [{ "name": "manager", "type": "address", "internalType": "address" }, { + "name": "receiver", "type": "address", "internalType": "address", }], - "outputs": [{ "name": "", "type": "address", "internalType": "address" }], "stateMutability": "view", }, { @@ -265,15 +306,41 @@ export const BorrowerOperations = [ }, { "type": "function", - "name": "setAddresses", + "name": "setBatchManagerAnnualInterestRate", + "inputs": [ + { "name": "_newAnnualInterestRate", "type": "uint128", "internalType": "uint128" }, + { "name": "_upperHint", "type": "uint256", "internalType": "uint256" }, + { "name": "_lowerHint", "type": "uint256", "internalType": "uint256" }, + { "name": "_maxUpfrontFee", "type": "uint256", "internalType": "uint256" }, + ], + "outputs": [], + "stateMutability": "nonpayable", + }, + { + "type": "function", + "name": "setInterestBatchManager", + "inputs": [ + { "name": "_troveId", "type": "uint256", "internalType": "uint256" }, + { "name": "_newBatchManager", "type": "address", "internalType": "address" }, + { "name": "_upperHint", "type": "uint256", "internalType": "uint256" }, + { "name": "_lowerHint", "type": "uint256", "internalType": "uint256" }, + { "name": "_maxUpfrontFee", "type": "uint256", "internalType": "uint256" }, + ], + "outputs": [], + "stateMutability": "nonpayable", + }, + { + "type": "function", + "name": "setInterestIndividualDelegate", "inputs": [ - { "name": "_activePoolAddress", "type": "address", "internalType": "address" }, - { "name": "_defaultPoolAddress", "type": "address", "internalType": "address" }, - { "name": "_gasPoolAddress", "type": "address", "internalType": "address" }, - { "name": "_collSurplusPoolAddress", "type": "address", "internalType": "address" }, - { "name": "_priceFeedAddress", "type": "address", "internalType": "address" }, - { "name": "_sortedTrovesAddress", "type": "address", "internalType": "address" }, - { "name": "_boldTokenAddress", "type": "address", "internalType": "address" }, + { "name": "_troveId", "type": "uint256", "internalType": "uint256" }, + { "name": "_delegate", "type": "address", "internalType": "address" }, + { "name": "_minInterestRate", "type": "uint128", "internalType": "uint128" }, + { "name": "_maxInterestRate", "type": "uint128", "internalType": "uint128" }, + { "name": "_newAnnualInterestRate", "type": "uint256", "internalType": "uint256" }, + { "name": "_upperHint", "type": "uint256", "internalType": "uint256" }, + { "name": "_lowerHint", "type": "uint256", "internalType": "uint256" }, + { "name": "_maxUpfrontFee", "type": "uint256", "internalType": "uint256" }, ], "outputs": [], "stateMutability": "nonpayable", @@ -291,7 +358,7 @@ export const BorrowerOperations = [ }, { "type": "function", - "name": "setRemoveManager", + "name": "setRemoveManagerWithReceiver", "inputs": [{ "name": "_troveId", "type": "uint256", "internalType": "uint256" }, { "name": "_manager", "type": "address", @@ -310,17 +377,18 @@ export const BorrowerOperations = [ }, { "type": "function", - "name": "sortedTroves", - "inputs": [], - "outputs": [{ "name": "", "type": "address", "internalType": "contract ISortedTroves" }], - "stateMutability": "view", - }, - { - "type": "function", - "name": "troveManager", - "inputs": [], - "outputs": [{ "name": "", "type": "address", "internalType": "contract ITroveManager" }], - "stateMutability": "view", + "name": "switchBatchManager", + "inputs": [ + { "name": "_troveId", "type": "uint256", "internalType": "uint256" }, + { "name": "_removeUpperHint", "type": "uint256", "internalType": "uint256" }, + { "name": "_removeLowerHint", "type": "uint256", "internalType": "uint256" }, + { "name": "_newBatchManager", "type": "address", "internalType": "address" }, + { "name": "_addUpperHint", "type": "uint256", "internalType": "uint256" }, + { "name": "_addLowerHint", "type": "uint256", "internalType": "uint256" }, + { "name": "_maxUpfrontFee", "type": "uint256", "internalType": "uint256" }, + ], + "outputs": [], + "stateMutability": "nonpayable", }, { "type": "function", @@ -347,7 +415,7 @@ export const BorrowerOperations = [ { "type": "event", "name": "ActivePoolAddressChanged", - "inputs": [{ "name": "_activePoolAddress", "type": "address", "indexed": false, "internalType": "address" }], + "inputs": [{ "name": "_newActivePoolAddress", "type": "address", "indexed": false, "internalType": "address" }], "anonymous": false, }, { @@ -365,7 +433,7 @@ export const BorrowerOperations = [ { "type": "event", "name": "DefaultPoolAddressChanged", - "inputs": [{ "name": "_defaultPoolAddress", "type": "address", "indexed": false, "internalType": "address" }], + "inputs": [{ "name": "_newDefaultPoolAddress", "type": "address", "indexed": false, "internalType": "address" }], "anonymous": false, }, { @@ -374,17 +442,6 @@ export const BorrowerOperations = [ "inputs": [{ "name": "_gasPoolAddress", "type": "address", "indexed": false, "internalType": "address" }], "anonymous": false, }, - { - "type": "event", - "name": "OwnershipTransferred", - "inputs": [{ "name": "previousOwner", "type": "address", "indexed": true, "internalType": "address" }, { - "name": "newOwner", - "type": "address", - "indexed": true, - "internalType": "address", - }], - "anonymous": false, - }, { "type": "event", "name": "PriceFeedAddressChanged", @@ -415,4 +472,49 @@ export const BorrowerOperations = [ "inputs": [{ "name": "_newTroveManagerAddress", "type": "address", "indexed": false, "internalType": "address" }], "anonymous": false, }, + { + "type": "event", + "name": "TroveNFTAddressChanged", + "inputs": [{ "name": "_newTroveNFTAddress", "type": "address", "indexed": false, "internalType": "address" }], + "anonymous": false, + }, + { "type": "error", "name": "AnnualManagementFeeTooHigh", "inputs": [] }, + { "type": "error", "name": "BatchInterestRateChangePeriodNotPassed", "inputs": [] }, + { "type": "error", "name": "BatchManagerExists", "inputs": [] }, + { "type": "error", "name": "BatchManagerNotNew", "inputs": [] }, + { "type": "error", "name": "BelowCriticalThreshold", "inputs": [] }, + { "type": "error", "name": "BorrowingNotPermittedBelowCT", "inputs": [] }, + { "type": "error", "name": "CallerNotPriceFeed", "inputs": [] }, + { "type": "error", "name": "CallerNotTroveManager", "inputs": [] }, + { "type": "error", "name": "CollWithdrawalTooHigh", "inputs": [] }, + { "type": "error", "name": "DebtBelowMin", "inputs": [] }, + { "type": "error", "name": "EmptyManager", "inputs": [] }, + { "type": "error", "name": "ICRBelowMCR", "inputs": [] }, + { "type": "error", "name": "InterestNotInRange", "inputs": [] }, + { "type": "error", "name": "InterestRateNotNew", "inputs": [] }, + { "type": "error", "name": "InterestRateTooHigh", "inputs": [] }, + { "type": "error", "name": "InterestRateTooLow", "inputs": [] }, + { "type": "error", "name": "InvalidInterestBatchManager", "inputs": [] }, + { "type": "error", "name": "IsShutDown", "inputs": [] }, + { "type": "error", "name": "MinGeMax", "inputs": [] }, + { "type": "error", "name": "MinInterestRateChangePeriodTooLow", "inputs": [] }, + { "type": "error", "name": "NewFeeNotLower", "inputs": [] }, + { "type": "error", "name": "NewOracleFailureDetected", "inputs": [] }, + { "type": "error", "name": "NotBorrower", "inputs": [] }, + { "type": "error", "name": "NotEnoughBoldBalance", "inputs": [] }, + { "type": "error", "name": "NotOwnerNorAddManager", "inputs": [] }, + { "type": "error", "name": "NotOwnerNorInterestManager", "inputs": [] }, + { "type": "error", "name": "NotOwnerNorRemoveManager", "inputs": [] }, + { "type": "error", "name": "NotShutDown", "inputs": [] }, + { "type": "error", "name": "RepaymentNotMatchingCollWithdrawal", "inputs": [] }, + { "type": "error", "name": "TCRBelowCCR", "inputs": [] }, + { "type": "error", "name": "TCRNotBelowSCR", "inputs": [] }, + { "type": "error", "name": "TroveInBatch", "inputs": [] }, + { "type": "error", "name": "TroveNotActive", "inputs": [] }, + { "type": "error", "name": "TroveNotInBatch", "inputs": [] }, + { "type": "error", "name": "TroveNotOpen", "inputs": [] }, + { "type": "error", "name": "TroveNotUnredeemable", "inputs": [] }, + { "type": "error", "name": "TroveOpen", "inputs": [] }, + { "type": "error", "name": "UpfrontFeeTooHigh", "inputs": [] }, + { "type": "error", "name": "ZeroAdjustment", "inputs": [] }, ] as const; diff --git a/frontend/app/src/abi/CollSurplusPool.ts b/frontend/app/src/abi/CollSurplusPool.ts index 6e18a7b5..8722915c 100644 --- a/frontend/app/src/abi/CollSurplusPool.ts +++ b/frontend/app/src/abi/CollSurplusPool.ts @@ -2,7 +2,7 @@ // please do not edit it manually export const CollSurplusPool = [{ "type": "constructor", - "inputs": [{ "name": "_collAddress", "type": "address", "internalType": "address" }], + "inputs": [{ "name": "_addressesRegistry", "type": "address", "internalType": "contract IAddressesRegistry" }], "stateMutability": "nonpayable", }, { "type": "function", @@ -20,12 +20,6 @@ export const CollSurplusPool = [{ }], "outputs": [], "stateMutability": "nonpayable", -}, { - "type": "function", - "name": "activePoolAddress", - "inputs": [], - "outputs": [{ "name": "", "type": "address", "internalType": "address" }], - "stateMutability": "view", }, { "type": "function", "name": "borrowerOperationsAddress", @@ -56,39 +50,12 @@ export const CollSurplusPool = [{ "inputs": [{ "name": "_account", "type": "address", "internalType": "address" }], "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], "stateMutability": "view", -}, { - "type": "function", - "name": "isOwner", - "inputs": [], - "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }], - "stateMutability": "view", -}, { - "type": "function", - "name": "owner", - "inputs": [], - "outputs": [{ "name": "", "type": "address", "internalType": "address" }], - "stateMutability": "view", -}, { - "type": "function", - "name": "setAddresses", - "inputs": [{ "name": "_borrowerOperationsAddress", "type": "address", "internalType": "address" }, { - "name": "_troveManagerAddress", - "type": "address", - "internalType": "address", - }, { "name": "_activePoolAddress", "type": "address", "internalType": "address" }], - "outputs": [], - "stateMutability": "nonpayable", }, { "type": "function", "name": "troveManagerAddress", "inputs": [], "outputs": [{ "name": "", "type": "address", "internalType": "address" }], "stateMutability": "view", -}, { - "type": "event", - "name": "ActivePoolAddressChanged", - "inputs": [{ "name": "_newActivePoolAddress", "type": "address", "indexed": false, "internalType": "address" }], - "anonymous": false, }, { "type": "event", "name": "BorrowerOperationsAddressChanged", @@ -119,16 +86,6 @@ export const CollSurplusPool = [{ "internalType": "uint256", }], "anonymous": false, -}, { - "type": "event", - "name": "OwnershipTransferred", - "inputs": [{ "name": "previousOwner", "type": "address", "indexed": true, "internalType": "address" }, { - "name": "newOwner", - "type": "address", - "indexed": true, - "internalType": "address", - }], - "anonymous": false, }, { "type": "event", "name": "TroveManagerAddressChanged", diff --git a/frontend/app/src/abi/CollateralRegistry.ts b/frontend/app/src/abi/CollateralRegistry.ts index 45a79f56..48878597 100644 --- a/frontend/app/src/abi/CollateralRegistry.ts +++ b/frontend/app/src/abi/CollateralRegistry.ts @@ -5,15 +5,9 @@ export const CollateralRegistry = [{ "inputs": [{ "name": "_boldToken", "type": "address", "internalType": "contract IBoldToken" }, { "name": "_tokens", "type": "address[]", - "internalType": "contract IERC20[]", + "internalType": "contract IERC20Metadata[]", }, { "name": "_troveManagers", "type": "address[]", "internalType": "contract ITroveManager[]" }], "stateMutability": "nonpayable", -}, { - "type": "function", - "name": "activePool", - "inputs": [], - "outputs": [{ "name": "", "type": "address", "internalType": "contract IActivePool" }], - "stateMutability": "view", }, { "type": "function", "name": "baseRate", @@ -26,30 +20,12 @@ export const CollateralRegistry = [{ "inputs": [], "outputs": [{ "name": "", "type": "address", "internalType": "contract IBoldToken" }], "stateMutability": "view", -}, { - "type": "function", - "name": "defaultPool", - "inputs": [], - "outputs": [{ "name": "", "type": "address", "internalType": "contract IDefaultPool" }], - "stateMutability": "view", }, { "type": "function", "name": "getEffectiveRedemptionFeeInBold", "inputs": [{ "name": "_redeemAmount", "type": "uint256", "internalType": "uint256" }], "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], "stateMutability": "view", -}, { - "type": "function", - "name": "getEntireSystemColl", - "inputs": [], - "outputs": [{ "name": "entireSystemColl", "type": "uint256", "internalType": "uint256" }], - "stateMutability": "view", -}, { - "type": "function", - "name": "getEntireSystemDebt", - "inputs": [], - "outputs": [{ "name": "entireSystemDebt", "type": "uint256", "internalType": "uint256" }], - "stateMutability": "view", }, { "type": "function", "name": "getRedemptionFeeWithDecay", @@ -78,7 +54,7 @@ export const CollateralRegistry = [{ "type": "function", "name": "getToken", "inputs": [{ "name": "_index", "type": "uint256", "internalType": "uint256" }], - "outputs": [{ "name": "", "type": "address", "internalType": "contract IERC20" }], + "outputs": [{ "name": "", "type": "address", "internalType": "contract IERC20Metadata" }], "stateMutability": "view", }, { "type": "function", @@ -92,12 +68,6 @@ export const CollateralRegistry = [{ "inputs": [], "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], "stateMutability": "view", -}, { - "type": "function", - "name": "priceFeed", - "inputs": [], - "outputs": [{ "name": "", "type": "address", "internalType": "contract IPriceFeed" }], - "stateMutability": "view", }, { "type": "function", "name": "redeemCollateral", diff --git a/frontend/app/src/abi/DefaultPool.ts b/frontend/app/src/abi/DefaultPool.ts index 88ca8cbb..7981c4dd 100644 --- a/frontend/app/src/abi/DefaultPool.ts +++ b/frontend/app/src/abi/DefaultPool.ts @@ -2,7 +2,7 @@ // please do not edit it manually export const DefaultPool = [{ "type": "constructor", - "inputs": [{ "name": "_collAddress", "type": "address", "internalType": "address" }], + "inputs": [{ "name": "_addressesRegistry", "type": "address", "internalType": "contract IAddressesRegistry" }], "stateMutability": "nonpayable", }, { "type": "function", @@ -46,18 +46,6 @@ export const DefaultPool = [{ "inputs": [{ "name": "_amount", "type": "uint256", "internalType": "uint256" }], "outputs": [], "stateMutability": "nonpayable", -}, { - "type": "function", - "name": "isOwner", - "inputs": [], - "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }], - "stateMutability": "view", -}, { - "type": "function", - "name": "owner", - "inputs": [], - "outputs": [{ "name": "", "type": "address", "internalType": "address" }], - "stateMutability": "view", }, { "type": "function", "name": "receiveColl", @@ -70,16 +58,6 @@ export const DefaultPool = [{ "inputs": [{ "name": "_amount", "type": "uint256", "internalType": "uint256" }], "outputs": [], "stateMutability": "nonpayable", -}, { - "type": "function", - "name": "setAddresses", - "inputs": [{ "name": "_troveManagerAddress", "type": "address", "internalType": "address" }, { - "name": "_activePoolAddress", - "type": "address", - "internalType": "address", - }], - "outputs": [], - "stateMutability": "nonpayable", }, { "type": "function", "name": "troveManagerAddress", @@ -91,6 +69,11 @@ export const DefaultPool = [{ "name": "ActivePoolAddressChanged", "inputs": [{ "name": "_newActivePoolAddress", "type": "address", "indexed": false, "internalType": "address" }], "anonymous": false, +}, { + "type": "event", + "name": "CollTokenAddressChanged", + "inputs": [{ "name": "_newCollTokenAddress", "type": "address", "indexed": false, "internalType": "address" }], + "anonymous": false, }, { "type": "event", "name": "DefaultPoolBoldDebtUpdated", @@ -111,16 +94,6 @@ export const DefaultPool = [{ "internalType": "uint256", }], "anonymous": false, -}, { - "type": "event", - "name": "OwnershipTransferred", - "inputs": [{ "name": "previousOwner", "type": "address", "indexed": true, "internalType": "address" }, { - "name": "newOwner", - "type": "address", - "indexed": true, - "internalType": "address", - }], - "anonymous": false, }, { "type": "event", "name": "TroveManagerAddressChanged", diff --git a/frontend/app/src/abi/GasPool.ts b/frontend/app/src/abi/GasPool.ts index 1a2c5c7f..8dce711c 100644 --- a/frontend/app/src/abi/GasPool.ts +++ b/frontend/app/src/abi/GasPool.ts @@ -2,10 +2,6 @@ // please do not edit it manually export const GasPool = [{ "type": "constructor", - "inputs": [{ "name": "_weth", "type": "address", "internalType": "contract IWETH" }, { - "name": "_borrowerOperations", - "type": "address", - "internalType": "contract IBorrowerOperations", - }, { "name": "_troveManager", "type": "address", "internalType": "contract ITroveManager" }], + "inputs": [{ "name": "_addressesRegistry", "type": "address", "internalType": "contract IAddressesRegistry" }], "stateMutability": "nonpayable", }] as const; diff --git a/frontend/app/src/abi/HintHelpers.ts b/frontend/app/src/abi/HintHelpers.ts index e2871223..d3482cc2 100644 --- a/frontend/app/src/abi/HintHelpers.ts +++ b/frontend/app/src/abi/HintHelpers.ts @@ -16,6 +16,26 @@ export const HintHelpers = [{ "inputs": [], "outputs": [{ "name": "", "type": "address", "internalType": "contract ICollateralRegistry" }], "stateMutability": "view", +}, { + "type": "function", + "name": "forcePredictAdjustInterestRateUpfrontFee", + "inputs": [{ "name": "_collIndex", "type": "uint256", "internalType": "uint256" }, { + "name": "_troveId", + "type": "uint256", + "internalType": "uint256", + }, { "name": "_newInterestRate", "type": "uint256", "internalType": "uint256" }], + "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], + "stateMutability": "view", +}, { + "type": "function", + "name": "forcePredictJoinBatchInterestRateUpfrontFee", + "inputs": [{ "name": "_collIndex", "type": "uint256", "internalType": "uint256" }, { + "name": "_troveId", + "type": "uint256", + "internalType": "uint256", + }, { "name": "_batchAddress", "type": "address", "internalType": "address" }], + "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], + "stateMutability": "view", }, { "type": "function", "name": "getApproxHint", @@ -31,6 +51,16 @@ export const HintHelpers = [{ "internalType": "uint256", }, { "name": "latestRandomSeed", "type": "uint256", "internalType": "uint256" }], "stateMutability": "view", +}, { + "type": "function", + "name": "predictAdjustBatchInterestRateUpfrontFee", + "inputs": [{ "name": "_collIndex", "type": "uint256", "internalType": "uint256" }, { + "name": "_batchAddress", + "type": "address", + "internalType": "address", + }, { "name": "_newInterestRate", "type": "uint256", "internalType": "uint256" }], + "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], + "stateMutability": "view", }, { "type": "function", "name": "predictAdjustInterestRateUpfrontFee", @@ -51,6 +81,26 @@ export const HintHelpers = [{ }, { "name": "_debtIncrease", "type": "uint256", "internalType": "uint256" }], "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], "stateMutability": "view", +}, { + "type": "function", + "name": "predictJoinBatchInterestRateUpfrontFee", + "inputs": [{ "name": "_collIndex", "type": "uint256", "internalType": "uint256" }, { + "name": "_troveId", + "type": "uint256", + "internalType": "uint256", + }, { "name": "_batchAddress", "type": "address", "internalType": "address" }], + "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], + "stateMutability": "view", +}, { + "type": "function", + "name": "predictOpenTroveAndJoinBatchUpfrontFee", + "inputs": [{ "name": "_collIndex", "type": "uint256", "internalType": "uint256" }, { + "name": "_borrowedAmount", + "type": "uint256", + "internalType": "uint256", + }, { "name": "_batchAddress", "type": "address", "internalType": "address" }], + "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], + "stateMutability": "view", }, { "type": "function", "name": "predictOpenTroveUpfrontFee", @@ -61,4 +111,14 @@ export const HintHelpers = [{ }, { "name": "_interestRate", "type": "uint256", "internalType": "uint256" }], "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], "stateMutability": "view", +}, { + "type": "function", + "name": "predictRemoveFromBatchUpfrontFee", + "inputs": [{ "name": "_collIndex", "type": "uint256", "internalType": "uint256" }, { + "name": "_troveId", + "type": "uint256", + "internalType": "uint256", + }, { "name": "_newInterestRate", "type": "uint256", "internalType": "uint256" }], + "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], + "stateMutability": "view", }] as const; diff --git a/frontend/app/src/abi/MultiTroveGetter.ts b/frontend/app/src/abi/MultiTroveGetter.ts index ff1d9e0c..cff5bace 100644 --- a/frontend/app/src/abi/MultiTroveGetter.ts +++ b/frontend/app/src/abi/MultiTroveGetter.ts @@ -10,6 +10,25 @@ export const MultiTroveGetter = [{ "inputs": [], "outputs": [{ "name": "", "type": "address", "internalType": "contract ICollateralRegistry" }], "stateMutability": "view", +}, { + "type": "function", + "name": "getDebtPerInterestRateAscending", + "inputs": [{ "name": "_collIndex", "type": "uint256", "internalType": "uint256" }, { + "name": "_startId", + "type": "uint256", + "internalType": "uint256", + }, { "name": "_maxIterations", "type": "uint256", "internalType": "uint256" }], + "outputs": [{ + "name": "data", + "type": "tuple[]", + "internalType": "struct IMultiTroveGetter.DebtPerInterestRate[]", + "components": [{ "name": "interestBatchManager", "type": "address", "internalType": "address" }, { + "name": "interestRate", + "type": "uint256", + "internalType": "uint256", + }, { "name": "debt", "type": "uint256", "internalType": "uint256" }], + }, { "name": "currId", "type": "uint256", "internalType": "uint256" }], + "stateMutability": "view", }, { "type": "function", "name": "getMultipleSortedTroves", @@ -21,7 +40,7 @@ export const MultiTroveGetter = [{ "outputs": [{ "name": "_troves", "type": "tuple[]", - "internalType": "struct MultiTroveGetter.CombinedTroveData[]", + "internalType": "struct IMultiTroveGetter.CombinedTroveData[]", "components": [ { "name": "id", "type": "uint256", "internalType": "uint256" }, { "name": "debt", "type": "uint256", "internalType": "uint256" }, @@ -30,6 +49,9 @@ export const MultiTroveGetter = [{ { "name": "annualInterestRate", "type": "uint256", "internalType": "uint256" }, { "name": "lastDebtUpdateTime", "type": "uint256", "internalType": "uint256" }, { "name": "lastInterestRateAdjTime", "type": "uint256", "internalType": "uint256" }, + { "name": "interestBatchManager", "type": "address", "internalType": "address" }, + { "name": "batchDebtShares", "type": "uint256", "internalType": "uint256" }, + { "name": "batchCollShares", "type": "uint256", "internalType": "uint256" }, { "name": "snapshotETH", "type": "uint256", "internalType": "uint256" }, { "name": "snapshotBoldDebt", "type": "uint256", "internalType": "uint256" }, ], diff --git a/frontend/app/src/abi/PriceFeed.ts b/frontend/app/src/abi/PriceFeed.ts index e4494715..e6983ba0 100644 --- a/frontend/app/src/abi/PriceFeed.ts +++ b/frontend/app/src/abi/PriceFeed.ts @@ -4,14 +4,18 @@ export const PriceFeed = [{ "type": "function", "name": "fetchPrice", "inputs": [], - "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], + "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }, { + "name": "", + "type": "bool", + "internalType": "bool", + }], "stateMutability": "view", }, { "type": "function", "name": "getEthUsdStalenessThreshold", "inputs": [], "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], - "stateMutability": "view", + "stateMutability": "pure", }, { "type": "function", "name": "getPrice", diff --git a/frontend/app/src/abi/SortedTroves.ts b/frontend/app/src/abi/SortedTroves.ts index 7c91bf9e..05a192b2 100644 --- a/frontend/app/src/abi/SortedTroves.ts +++ b/frontend/app/src/abi/SortedTroves.ts @@ -1,6 +1,10 @@ // this file was generated by scripts/update-liquity-abis.ts // please do not edit it manually -export const SortedTroves = [{ "type": "constructor", "inputs": [], "stateMutability": "nonpayable" }, { +export const SortedTroves = [{ + "type": "constructor", + "inputs": [{ "name": "_addressesRegistry", "type": "address", "internalType": "contract IAddressesRegistry" }], + "stateMutability": "nonpayable", +}, { "type": "function", "name": "NAME", "inputs": [], @@ -109,8 +113,8 @@ export const SortedTroves = [{ "type": "constructor", "inputs": [], "stateMutabi "stateMutability": "view", }, { "type": "function", - "name": "isOwner", - "inputs": [], + "name": "isEmptyBatch", + "inputs": [{ "name": "_id", "type": "address", "internalType": "BatchId" }], "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }], "stateMutability": "view", }, { @@ -124,12 +128,6 @@ export const SortedTroves = [{ "type": "constructor", "inputs": [], "stateMutabi { "name": "exists", "type": "bool", "internalType": "bool" }, ], "stateMutability": "view", -}, { - "type": "function", - "name": "owner", - "inputs": [], - "outputs": [{ "name": "", "type": "address", "internalType": "address" }], - "stateMutability": "view", }, { "type": "function", "name": "reInsert", @@ -164,16 +162,6 @@ export const SortedTroves = [{ "type": "constructor", "inputs": [], "stateMutabi "inputs": [{ "name": "_id", "type": "uint256", "internalType": "uint256" }], "outputs": [], "stateMutability": "nonpayable", -}, { - "type": "function", - "name": "setAddresses", - "inputs": [{ "name": "_troveManagerAddress", "type": "address", "internalType": "address" }, { - "name": "_borrowerOperationsAddress", - "type": "address", - "internalType": "address", - }], - "outputs": [], - "stateMutability": "nonpayable", }, { "type": "function", "name": "size", @@ -201,16 +189,6 @@ export const SortedTroves = [{ "type": "constructor", "inputs": [], "stateMutabi "name": "BorrowerOperationsAddressChanged", "inputs": [{ "name": "_borrowerOperationsAddress", "type": "address", "indexed": false, "internalType": "address" }], "anonymous": false, -}, { - "type": "event", - "name": "OwnershipTransferred", - "inputs": [{ "name": "previousOwner", "type": "address", "indexed": true, "internalType": "address" }, { - "name": "newOwner", - "type": "address", - "indexed": true, - "internalType": "address", - }], - "anonymous": false, }, { "type": "event", "name": "TroveManagerAddressChanged", diff --git a/frontend/app/src/abi/StabilityPool.ts b/frontend/app/src/abi/StabilityPool.ts index caebe3c2..dda481ab 100644 --- a/frontend/app/src/abi/StabilityPool.ts +++ b/frontend/app/src/abi/StabilityPool.ts @@ -3,7 +3,7 @@ export const StabilityPool = [ { "type": "constructor", - "inputs": [{ "name": "_collAddress", "type": "address", "internalType": "address" }], + "inputs": [{ "name": "_addressesRegistry", "type": "address", "internalType": "contract IAddressesRegistry" }], "stateMutability": "nonpayable", }, { @@ -41,13 +41,6 @@ export const StabilityPool = [ "outputs": [{ "name": "", "type": "address", "internalType": "contract IBoldToken" }], "stateMutability": "view", }, - { - "type": "function", - "name": "borrowerOperations", - "inputs": [], - "outputs": [{ "name": "", "type": "address", "internalType": "contract IBorrowerOperations" }], - "stateMutability": "view", - }, { "type": "function", "name": "claimAllCollGains", "inputs": [], "outputs": [], "stateMutability": "nonpayable" }, { "type": "function", @@ -70,13 +63,6 @@ export const StabilityPool = [ "outputs": [{ "name": "", "type": "uint128", "internalType": "uint128" }], "stateMutability": "view", }, - { - "type": "function", - "name": "defaultPool", - "inputs": [], - "outputs": [{ "name": "", "type": "address", "internalType": "contract IDefaultPool" }], - "stateMutability": "view", - }, { "type": "function", "name": "depositSnapshots", @@ -184,9 +170,9 @@ export const StabilityPool = [ }, { "type": "function", - "name": "isOwner", + "name": "getYieldGainsPending", "inputs": [], - "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }], + "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], "stateMutability": "view", }, { @@ -221,20 +207,6 @@ export const StabilityPool = [ "outputs": [], "stateMutability": "nonpayable", }, - { - "type": "function", - "name": "owner", - "inputs": [], - "outputs": [{ "name": "", "type": "address", "internalType": "address" }], - "stateMutability": "view", - }, - { - "type": "function", - "name": "priceFeed", - "inputs": [], - "outputs": [{ "name": "", "type": "address", "internalType": "contract IPriceFeed" }], - "stateMutability": "view", - }, { "type": "function", "name": "provideToSP", @@ -246,27 +218,6 @@ export const StabilityPool = [ "outputs": [], "stateMutability": "nonpayable", }, - { - "type": "function", - "name": "setAddresses", - "inputs": [ - { "name": "_borrowerOperationsAddress", "type": "address", "internalType": "address" }, - { "name": "_troveManagerAddress", "type": "address", "internalType": "address" }, - { "name": "_activePoolAddress", "type": "address", "internalType": "address" }, - { "name": "_boldTokenAddress", "type": "address", "internalType": "address" }, - { "name": "_sortedTrovesAddress", "type": "address", "internalType": "address" }, - { "name": "_priceFeedAddress", "type": "address", "internalType": "address" }, - ], - "outputs": [], - "stateMutability": "nonpayable", - }, - { - "type": "function", - "name": "sortedTroves", - "inputs": [], - "outputs": [{ "name": "", "type": "address", "internalType": "contract ISortedTroves" }], - "stateMutability": "view", - }, { "type": "function", "name": "stashedColl", @@ -322,17 +273,6 @@ export const StabilityPool = [ "inputs": [{ "name": "_newBoldTokenAddress", "type": "address", "indexed": false, "internalType": "address" }], "anonymous": false, }, - { - "type": "event", - "name": "BorrowerOperationsAddressChanged", - "inputs": [{ - "name": "_newBorrowerOperationsAddress", - "type": "address", - "indexed": false, - "internalType": "address", - }], - "anonymous": false, - }, { "type": "event", "name": "DefaultPoolAddressChanged", @@ -391,17 +331,6 @@ export const StabilityPool = [ }], "anonymous": false, }, - { - "type": "event", - "name": "OwnershipTransferred", - "inputs": [{ "name": "previousOwner", "type": "address", "indexed": true, "internalType": "address" }, { - "name": "newOwner", - "type": "address", - "indexed": true, - "internalType": "address", - }], - "anonymous": false, - }, { "type": "event", "name": "P_Updated", @@ -431,12 +360,6 @@ export const StabilityPool = [ "inputs": [{ "name": "_currentScale", "type": "uint128", "indexed": false, "internalType": "uint128" }], "anonymous": false, }, - { - "type": "event", - "name": "SortedTrovesAddressChanged", - "inputs": [{ "name": "_newSortedTrovesAddress", "type": "address", "indexed": false, "internalType": "address" }], - "anonymous": false, - }, { "type": "event", "name": "StabilityPoolBoldBalanceUpdated", diff --git a/frontend/app/src/abi/TroveManager.ts b/frontend/app/src/abi/TroveManager.ts index 8d16db2b..b301fdcd 100644 --- a/frontend/app/src/abi/TroveManager.ts +++ b/frontend/app/src/abi/TroveManager.ts @@ -3,14 +3,7 @@ export const TroveManager = [ { "type": "constructor", - "inputs": [ - { "name": "_ccr", "type": "uint256", "internalType": "uint256" }, - { "name": "_mcr", "type": "uint256", "internalType": "uint256" }, - { "name": "_scr", "type": "uint256", "internalType": "uint256" }, - { "name": "_liquidationPenaltySP", "type": "uint256", "internalType": "uint256" }, - { "name": "_liquidationPenaltyRedistribution", "type": "uint256", "internalType": "uint256" }, - { "name": "_weth", "type": "address", "internalType": "contract IWETH" }, - ], + "inputs": [{ "name": "_addressesRegistry", "type": "address", "internalType": "contract IAddressesRegistry" }], "stateMutability": "nonpayable", }, { @@ -20,69 +13,6 @@ export const TroveManager = [ "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], "stateMutability": "view", }, - { - "type": "function", - "name": "LIQUIDATION_PENALTY_REDISTRIBUTION", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], - "stateMutability": "view", - }, - { - "type": "function", - "name": "LIQUIDATION_PENALTY_SP", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], - "stateMutability": "view", - }, - { - "type": "function", - "name": "L_boldDebt", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], - "stateMutability": "view", - }, - { - "type": "function", - "name": "L_coll", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], - "stateMutability": "view", - }, - { - "type": "function", - "name": "MCR", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], - "stateMutability": "view", - }, - { - "type": "function", - "name": "NAME", - "inputs": [], - "outputs": [{ "name": "", "type": "string", "internalType": "string" }], - "stateMutability": "view", - }, - { - "type": "function", - "name": "SCR", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], - "stateMutability": "view", - }, - { - "type": "function", - "name": "SYMBOL", - "inputs": [], - "outputs": [{ "name": "", "type": "string", "internalType": "string" }], - "stateMutability": "view", - }, - { - "type": "function", - "name": "TroveIds", - "inputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], - "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], - "stateMutability": "view", - }, { "type": "function", "name": "Troves", @@ -96,16 +26,11 @@ export const TroveManager = [ { "name": "lastDebtUpdateTime", "type": "uint64", "internalType": "uint64" }, { "name": "lastInterestRateAdjTime", "type": "uint64", "internalType": "uint64" }, { "name": "annualInterestRate", "type": "uint256", "internalType": "uint256" }, + { "name": "interestBatchManager", "type": "address", "internalType": "address" }, + { "name": "batchDebtShares", "type": "uint256", "internalType": "uint256" }, ], "stateMutability": "view", }, - { - "type": "function", - "name": "WETH", - "inputs": [], - "outputs": [{ "name": "", "type": "address", "internalType": "contract IWETH" }], - "stateMutability": "view", - }, { "type": "function", "name": "activePool", @@ -115,20 +40,9 @@ export const TroveManager = [ }, { "type": "function", - "name": "approve", - "inputs": [{ "name": "to", "type": "address", "internalType": "address" }, { - "name": "tokenId", - "type": "uint256", - "internalType": "uint256", - }], - "outputs": [], - "stateMutability": "nonpayable", - }, - { - "type": "function", - "name": "balanceOf", - "inputs": [{ "name": "owner", "type": "address", "internalType": "address" }], - "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], + "name": "batchIds", + "inputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], + "outputs": [{ "name": "", "type": "address", "internalType": "address" }], "stateMutability": "view", }, { @@ -140,72 +54,9 @@ export const TroveManager = [ }, { "type": "function", - "name": "boldToken", + "name": "borrowerOperations", "inputs": [], - "outputs": [{ "name": "", "type": "address", "internalType": "contract IBoldToken" }], - "stateMutability": "view", - }, - { - "type": "function", - "name": "borrowerOperationsAddress", - "inputs": [], - "outputs": [{ "name": "", "type": "address", "internalType": "address" }], - "stateMutability": "view", - }, - { - "type": "function", - "name": "calcTroveAccruedInterest", - "inputs": [{ "name": "_troveId", "type": "uint256", "internalType": "uint256" }], - "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], - "stateMutability": "view", - }, - { - "type": "function", - "name": "checkBelowCriticalThreshold", - "inputs": [{ "name": "_price", "type": "uint256", "internalType": "uint256" }], - "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }], - "stateMutability": "view", - }, - { - "type": "function", - "name": "checkTroveIsActive", - "inputs": [{ "name": "_troveId", "type": "uint256", "internalType": "uint256" }], - "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }], - "stateMutability": "view", - }, - { - "type": "function", - "name": "checkTroveIsOpen", - "inputs": [{ "name": "_troveId", "type": "uint256", "internalType": "uint256" }], - "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }], - "stateMutability": "view", - }, - { - "type": "function", - "name": "checkTroveIsUnredeemable", - "inputs": [{ "name": "_troveId", "type": "uint256", "internalType": "uint256" }], - "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }], - "stateMutability": "view", - }, - { - "type": "function", - "name": "collateralRegistryAddress", - "inputs": [], - "outputs": [{ "name": "", "type": "address", "internalType": "address" }], - "stateMutability": "view", - }, - { - "type": "function", - "name": "defaultPool", - "inputs": [], - "outputs": [{ "name": "", "type": "address", "internalType": "contract IDefaultPool" }], - "stateMutability": "view", - }, - { - "type": "function", - "name": "getApproved", - "inputs": [{ "name": "tokenId", "type": "uint256", "internalType": "uint256" }], - "outputs": [{ "name": "", "type": "address", "internalType": "address" }], + "outputs": [{ "name": "", "type": "address", "internalType": "contract IBorrowerOperations" }], "stateMutability": "view", }, { @@ -219,19 +70,6 @@ export const TroveManager = [ "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], "stateMutability": "view", }, - { - "type": "function", - "name": "getEntireDebtAndColl", - "inputs": [{ "name": "_troveId", "type": "uint256", "internalType": "uint256" }], - "outputs": [ - { "name": "entireDebt", "type": "uint256", "internalType": "uint256" }, - { "name": "entireColl", "type": "uint256", "internalType": "uint256" }, - { "name": "pendingBoldDebtReward", "type": "uint256", "internalType": "uint256" }, - { "name": "pendingCollReward", "type": "uint256", "internalType": "uint256" }, - { "name": "accruedTroveInterest", "type": "uint256", "internalType": "uint256" }, - ], - "stateMutability": "view", - }, { "type": "function", "name": "getEntireSystemColl", @@ -246,6 +84,30 @@ export const TroveManager = [ "outputs": [{ "name": "entireSystemDebt", "type": "uint256", "internalType": "uint256" }], "stateMutability": "view", }, + { + "type": "function", + "name": "getLatestBatchData", + "inputs": [{ "name": "_batchAddress", "type": "address", "internalType": "address" }], + "outputs": [{ + "name": "batch", + "type": "tuple", + "internalType": "struct LatestBatchData", + "components": [ + { "name": "entireDebtWithoutRedistribution", "type": "uint256", "internalType": "uint256" }, + { "name": "entireCollWithoutRedistribution", "type": "uint256", "internalType": "uint256" }, + { "name": "accruedInterest", "type": "uint256", "internalType": "uint256" }, + { "name": "recordedDebt", "type": "uint256", "internalType": "uint256" }, + { "name": "annualInterestRate", "type": "uint256", "internalType": "uint256" }, + { "name": "weightedRecordedDebt", "type": "uint256", "internalType": "uint256" }, + { "name": "annualManagementFee", "type": "uint256", "internalType": "uint256" }, + { "name": "accruedManagementFee", "type": "uint256", "internalType": "uint256" }, + { "name": "weightedRecordedBatchManagementFee", "type": "uint256", "internalType": "uint256" }, + { "name": "lastDebtUpdateTime", "type": "uint256", "internalType": "uint256" }, + { "name": "lastInterestRateAdjTime", "type": "uint256", "internalType": "uint256" }, + ], + }], + "stateMutability": "view", + }, { "type": "function", "name": "getLatestTroveData", @@ -263,32 +125,12 @@ export const TroveManager = [ { "name": "recordedDebt", "type": "uint256", "internalType": "uint256" }, { "name": "annualInterestRate", "type": "uint256", "internalType": "uint256" }, { "name": "weightedRecordedDebt", "type": "uint256", "internalType": "uint256" }, + { "name": "accruedBatchManagementFee", "type": "uint256", "internalType": "uint256" }, { "name": "lastInterestRateAdjTime", "type": "uint256", "internalType": "uint256" }, ], }], "stateMutability": "view", }, - { - "type": "function", - "name": "getPendingBoldDebtReward", - "inputs": [{ "name": "_troveId", "type": "uint256", "internalType": "uint256" }], - "outputs": [{ "name": "redistBoldDebtGain", "type": "uint256", "internalType": "uint256" }], - "stateMutability": "view", - }, - { - "type": "function", - "name": "getPendingCollReward", - "inputs": [{ "name": "_troveId", "type": "uint256", "internalType": "uint256" }], - "outputs": [{ "name": "redistCollGain", "type": "uint256", "internalType": "uint256" }], - "stateMutability": "view", - }, - { - "type": "function", - "name": "getTCR", - "inputs": [{ "name": "_price", "type": "uint256", "internalType": "uint256" }], - "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], - "stateMutability": "view", - }, { "type": "function", "name": "getTroveAnnualInterestRate", @@ -296,34 +138,6 @@ export const TroveManager = [ "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], "stateMutability": "view", }, - { - "type": "function", - "name": "getTroveColl", - "inputs": [{ "name": "_troveId", "type": "uint256", "internalType": "uint256" }], - "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], - "stateMutability": "view", - }, - { - "type": "function", - "name": "getTroveDebt", - "inputs": [{ "name": "_troveId", "type": "uint256", "internalType": "uint256" }], - "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], - "stateMutability": "view", - }, - { - "type": "function", - "name": "getTroveEntireColl", - "inputs": [{ "name": "_troveId", "type": "uint256", "internalType": "uint256" }], - "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], - "stateMutability": "view", - }, - { - "type": "function", - "name": "getTroveEntireDebt", - "inputs": [{ "name": "_troveId", "type": "uint256", "internalType": "uint256" }], - "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], - "stateMutability": "view", - }, { "type": "function", "name": "getTroveFromTroveIdsArray", @@ -338,20 +152,6 @@ export const TroveManager = [ "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], "stateMutability": "view", }, - { - "type": "function", - "name": "getTroveLastDebtUpdateTime", - "inputs": [{ "name": "_troveId", "type": "uint256", "internalType": "uint256" }], - "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], - "stateMutability": "view", - }, - { - "type": "function", - "name": "getTroveStake", - "inputs": [{ "name": "_troveId", "type": "uint256", "internalType": "uint256" }], - "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], - "stateMutability": "view", - }, { "type": "function", "name": "getTroveStatus", @@ -359,13 +159,6 @@ export const TroveManager = [ "outputs": [{ "name": "", "type": "uint8", "internalType": "enum ITroveManager.Status" }], "stateMutability": "view", }, - { - "type": "function", - "name": "getTroveWeightedRecordedDebt", - "inputs": [{ "name": "_troveId", "type": "uint256", "internalType": "uint256" }], - "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], - "stateMutability": "view", - }, { "type": "function", "name": "getUnbackedPortionPriceAndRedeemability", @@ -379,64 +172,40 @@ export const TroveManager = [ }, { "type": "function", - "name": "hasRedistributionGains", - "inputs": [{ "name": "_troveId", "type": "uint256", "internalType": "uint256" }], - "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }], - "stateMutability": "view", - }, - { - "type": "function", - "name": "isApprovedForAll", - "inputs": [{ "name": "owner", "type": "address", "internalType": "address" }, { - "name": "operator", - "type": "address", - "internalType": "address", - }], - "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }], - "stateMutability": "view", - }, - { - "type": "function", - "name": "isOwner", - "inputs": [], - "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }], - "stateMutability": "view", - }, - { - "type": "function", - "name": "lastBoldDebtError_Redistribution", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], - "stateMutability": "view", - }, - { - "type": "function", - "name": "lastCollError_Redistribution", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], - "stateMutability": "view", - }, - { - "type": "function", - "name": "liquidate", - "inputs": [{ "name": "_troveId", "type": "uint256", "internalType": "uint256" }], + "name": "onAdjustTrove", + "inputs": [ + { "name": "_troveId", "type": "uint256", "internalType": "uint256" }, + { "name": "_newColl", "type": "uint256", "internalType": "uint256" }, + { "name": "_newDebt", "type": "uint256", "internalType": "uint256" }, + { + "name": "_troveChange", + "type": "tuple", + "internalType": "struct TroveChange", + "components": [ + { "name": "appliedRedistBoldDebtGain", "type": "uint256", "internalType": "uint256" }, + { "name": "appliedRedistCollGain", "type": "uint256", "internalType": "uint256" }, + { "name": "collIncrease", "type": "uint256", "internalType": "uint256" }, + { "name": "collDecrease", "type": "uint256", "internalType": "uint256" }, + { "name": "debtIncrease", "type": "uint256", "internalType": "uint256" }, + { "name": "debtDecrease", "type": "uint256", "internalType": "uint256" }, + { "name": "newWeightedRecordedDebt", "type": "uint256", "internalType": "uint256" }, + { "name": "oldWeightedRecordedDebt", "type": "uint256", "internalType": "uint256" }, + { "name": "upfrontFee", "type": "uint256", "internalType": "uint256" }, + { "name": "batchAccruedManagementFee", "type": "uint256", "internalType": "uint256" }, + { "name": "newWeightedRecordedBatchManagementFee", "type": "uint256", "internalType": "uint256" }, + { "name": "oldWeightedRecordedBatchManagementFee", "type": "uint256", "internalType": "uint256" }, + ], + }, + ], "outputs": [], "stateMutability": "nonpayable", }, { "type": "function", - "name": "name", - "inputs": [], - "outputs": [{ "name": "", "type": "string", "internalType": "string" }], - "stateMutability": "view", - }, - { - "type": "function", - "name": "onAdjustTrove", + "name": "onAdjustTroveInsideBatch", "inputs": [ { "name": "_troveId", "type": "uint256", "internalType": "uint256" }, - { "name": "_newColl", "type": "uint256", "internalType": "uint256" }, - { "name": "_newDebt", "type": "uint256", "internalType": "uint256" }, + { "name": "_newTroveColl", "type": "uint256", "internalType": "uint256" }, { "name": "_troveChange", "type": "tuple", @@ -451,8 +220,14 @@ export const TroveManager = [ { "name": "newWeightedRecordedDebt", "type": "uint256", "internalType": "uint256" }, { "name": "oldWeightedRecordedDebt", "type": "uint256", "internalType": "uint256" }, { "name": "upfrontFee", "type": "uint256", "internalType": "uint256" }, + { "name": "batchAccruedManagementFee", "type": "uint256", "internalType": "uint256" }, + { "name": "newWeightedRecordedBatchManagementFee", "type": "uint256", "internalType": "uint256" }, + { "name": "oldWeightedRecordedBatchManagementFee", "type": "uint256", "internalType": "uint256" }, ], }, + { "name": "_batchAddress", "type": "address", "internalType": "address" }, + { "name": "_newBatchColl", "type": "uint256", "internalType": "uint256" }, + { "name": "_newBatchDebt", "type": "uint256", "internalType": "uint256" }, ], "outputs": [], "stateMutability": "nonpayable", @@ -479,6 +254,9 @@ export const TroveManager = [ { "name": "newWeightedRecordedDebt", "type": "uint256", "internalType": "uint256" }, { "name": "oldWeightedRecordedDebt", "type": "uint256", "internalType": "uint256" }, { "name": "upfrontFee", "type": "uint256", "internalType": "uint256" }, + { "name": "batchAccruedManagementFee", "type": "uint256", "internalType": "uint256" }, + { "name": "newWeightedRecordedBatchManagementFee", "type": "uint256", "internalType": "uint256" }, + { "name": "oldWeightedRecordedBatchManagementFee", "type": "uint256", "internalType": "uint256" }, ], }, ], @@ -490,8 +268,11 @@ export const TroveManager = [ "name": "onApplyTroveInterest", "inputs": [ { "name": "_troveId", "type": "uint256", "internalType": "uint256" }, - { "name": "_newColl", "type": "uint256", "internalType": "uint256" }, - { "name": "_newDebt", "type": "uint256", "internalType": "uint256" }, + { "name": "_newTroveColl", "type": "uint256", "internalType": "uint256" }, + { "name": "_newTroveDebt", "type": "uint256", "internalType": "uint256" }, + { "name": "_batchAddress", "type": "address", "internalType": "address" }, + { "name": "_newBatchColl", "type": "uint256", "internalType": "uint256" }, + { "name": "_newBatchDebt", "type": "uint256", "internalType": "uint256" }, { "name": "_troveChange", "type": "tuple", @@ -506,6 +287,9 @@ export const TroveManager = [ { "name": "newWeightedRecordedDebt", "type": "uint256", "internalType": "uint256" }, { "name": "oldWeightedRecordedDebt", "type": "uint256", "internalType": "uint256" }, { "name": "upfrontFee", "type": "uint256", "internalType": "uint256" }, + { "name": "batchAccruedManagementFee", "type": "uint256", "internalType": "uint256" }, + { "name": "newWeightedRecordedBatchManagementFee", "type": "uint256", "internalType": "uint256" }, + { "name": "oldWeightedRecordedBatchManagementFee", "type": "uint256", "internalType": "uint256" }, ], }, ], @@ -515,7 +299,54 @@ export const TroveManager = [ { "type": "function", "name": "onCloseTrove", - "inputs": [{ "name": "_troveId", "type": "uint256", "internalType": "uint256" }, { + "inputs": [ + { "name": "_troveId", "type": "uint256", "internalType": "uint256" }, + { + "name": "_troveChange", + "type": "tuple", + "internalType": "struct TroveChange", + "components": [ + { "name": "appliedRedistBoldDebtGain", "type": "uint256", "internalType": "uint256" }, + { "name": "appliedRedistCollGain", "type": "uint256", "internalType": "uint256" }, + { "name": "collIncrease", "type": "uint256", "internalType": "uint256" }, + { "name": "collDecrease", "type": "uint256", "internalType": "uint256" }, + { "name": "debtIncrease", "type": "uint256", "internalType": "uint256" }, + { "name": "debtDecrease", "type": "uint256", "internalType": "uint256" }, + { "name": "newWeightedRecordedDebt", "type": "uint256", "internalType": "uint256" }, + { "name": "oldWeightedRecordedDebt", "type": "uint256", "internalType": "uint256" }, + { "name": "upfrontFee", "type": "uint256", "internalType": "uint256" }, + { "name": "batchAccruedManagementFee", "type": "uint256", "internalType": "uint256" }, + { "name": "newWeightedRecordedBatchManagementFee", "type": "uint256", "internalType": "uint256" }, + { "name": "oldWeightedRecordedBatchManagementFee", "type": "uint256", "internalType": "uint256" }, + ], + }, + { "name": "_batchAddress", "type": "address", "internalType": "address" }, + { "name": "_newBatchColl", "type": "uint256", "internalType": "uint256" }, + { "name": "_newBatchDebt", "type": "uint256", "internalType": "uint256" }, + ], + "outputs": [], + "stateMutability": "nonpayable", + }, + { + "type": "function", + "name": "onLowerBatchManagerAnnualFee", + "inputs": [ + { "name": "_batchAddress", "type": "address", "internalType": "address" }, + { "name": "_newColl", "type": "uint256", "internalType": "uint256" }, + { "name": "_newDebt", "type": "uint256", "internalType": "uint256" }, + { "name": "_newAnnualManagementFee", "type": "uint256", "internalType": "uint256" }, + ], + "outputs": [], + "stateMutability": "nonpayable", + }, + { + "type": "function", + "name": "onOpenTrove", + "inputs": [{ "name": "_owner", "type": "address", "internalType": "address" }, { + "name": "_troveId", + "type": "uint256", + "internalType": "uint256", + }, { "name": "_troveChange", "type": "tuple", "internalType": "struct TroveChange", @@ -529,45 +360,141 @@ export const TroveManager = [ { "name": "newWeightedRecordedDebt", "type": "uint256", "internalType": "uint256" }, { "name": "oldWeightedRecordedDebt", "type": "uint256", "internalType": "uint256" }, { "name": "upfrontFee", "type": "uint256", "internalType": "uint256" }, + { "name": "batchAccruedManagementFee", "type": "uint256", "internalType": "uint256" }, + { "name": "newWeightedRecordedBatchManagementFee", "type": "uint256", "internalType": "uint256" }, + { "name": "oldWeightedRecordedBatchManagementFee", "type": "uint256", "internalType": "uint256" }, ], - }], + }, { "name": "_annualInterestRate", "type": "uint256", "internalType": "uint256" }], "outputs": [], "stateMutability": "nonpayable", }, { "type": "function", - "name": "onOpenTrove", + "name": "onOpenTroveAndJoinBatch", "inputs": [ { "name": "_owner", "type": "address", "internalType": "address" }, { "name": "_troveId", "type": "uint256", "internalType": "uint256" }, - { "name": "_coll", "type": "uint256", "internalType": "uint256" }, - { "name": "_debt", "type": "uint256", "internalType": "uint256" }, - { "name": "_annualInterestRate", "type": "uint256", "internalType": "uint256" }, - { "name": "_upfrontFee", "type": "uint256", "internalType": "uint256" }, + { + "name": "_troveChange", + "type": "tuple", + "internalType": "struct TroveChange", + "components": [ + { "name": "appliedRedistBoldDebtGain", "type": "uint256", "internalType": "uint256" }, + { "name": "appliedRedistCollGain", "type": "uint256", "internalType": "uint256" }, + { "name": "collIncrease", "type": "uint256", "internalType": "uint256" }, + { "name": "collDecrease", "type": "uint256", "internalType": "uint256" }, + { "name": "debtIncrease", "type": "uint256", "internalType": "uint256" }, + { "name": "debtDecrease", "type": "uint256", "internalType": "uint256" }, + { "name": "newWeightedRecordedDebt", "type": "uint256", "internalType": "uint256" }, + { "name": "oldWeightedRecordedDebt", "type": "uint256", "internalType": "uint256" }, + { "name": "upfrontFee", "type": "uint256", "internalType": "uint256" }, + { "name": "batchAccruedManagementFee", "type": "uint256", "internalType": "uint256" }, + { "name": "newWeightedRecordedBatchManagementFee", "type": "uint256", "internalType": "uint256" }, + { "name": "oldWeightedRecordedBatchManagementFee", "type": "uint256", "internalType": "uint256" }, + ], + }, + { "name": "_batchAddress", "type": "address", "internalType": "address" }, + { "name": "_batchColl", "type": "uint256", "internalType": "uint256" }, + { "name": "_batchDebt", "type": "uint256", "internalType": "uint256" }, ], "outputs": [], "stateMutability": "nonpayable", }, { "type": "function", - "name": "owner", - "inputs": [], - "outputs": [{ "name": "", "type": "address", "internalType": "address" }], - "stateMutability": "view", + "name": "onRegisterBatchManager", + "inputs": [{ "name": "_account", "type": "address", "internalType": "address" }, { + "name": "_annualInterestRate", + "type": "uint256", + "internalType": "uint256", + }, { "name": "_annualManagementFee", "type": "uint256", "internalType": "uint256" }], + "outputs": [], + "stateMutability": "nonpayable", }, { "type": "function", - "name": "ownerOf", - "inputs": [{ "name": "tokenId", "type": "uint256", "internalType": "uint256" }], - "outputs": [{ "name": "", "type": "address", "internalType": "address" }], - "stateMutability": "view", + "name": "onRemoveFromBatch", + "inputs": [ + { "name": "_troveId", "type": "uint256", "internalType": "uint256" }, + { "name": "_newTroveColl", "type": "uint256", "internalType": "uint256" }, + { "name": "_newTroveDebt", "type": "uint256", "internalType": "uint256" }, + { + "name": "_troveChange", + "type": "tuple", + "internalType": "struct TroveChange", + "components": [ + { "name": "appliedRedistBoldDebtGain", "type": "uint256", "internalType": "uint256" }, + { "name": "appliedRedistCollGain", "type": "uint256", "internalType": "uint256" }, + { "name": "collIncrease", "type": "uint256", "internalType": "uint256" }, + { "name": "collDecrease", "type": "uint256", "internalType": "uint256" }, + { "name": "debtIncrease", "type": "uint256", "internalType": "uint256" }, + { "name": "debtDecrease", "type": "uint256", "internalType": "uint256" }, + { "name": "newWeightedRecordedDebt", "type": "uint256", "internalType": "uint256" }, + { "name": "oldWeightedRecordedDebt", "type": "uint256", "internalType": "uint256" }, + { "name": "upfrontFee", "type": "uint256", "internalType": "uint256" }, + { "name": "batchAccruedManagementFee", "type": "uint256", "internalType": "uint256" }, + { "name": "newWeightedRecordedBatchManagementFee", "type": "uint256", "internalType": "uint256" }, + { "name": "oldWeightedRecordedBatchManagementFee", "type": "uint256", "internalType": "uint256" }, + ], + }, + { "name": "_batchAddress", "type": "address", "internalType": "address" }, + { "name": "_newBatchColl", "type": "uint256", "internalType": "uint256" }, + { "name": "_newBatchDebt", "type": "uint256", "internalType": "uint256" }, + { "name": "_newAnnualInterestRate", "type": "uint256", "internalType": "uint256" }, + ], + "outputs": [], + "stateMutability": "nonpayable", }, { "type": "function", - "name": "priceFeed", - "inputs": [], - "outputs": [{ "name": "", "type": "address", "internalType": "contract IPriceFeed" }], - "stateMutability": "view", + "name": "onSetBatchManagerAnnualInterestRate", + "inputs": [ + { "name": "_batchAddress", "type": "address", "internalType": "address" }, + { "name": "_newColl", "type": "uint256", "internalType": "uint256" }, + { "name": "_newDebt", "type": "uint256", "internalType": "uint256" }, + { "name": "_newAnnualInterestRate", "type": "uint256", "internalType": "uint256" }, + { "name": "_upfrontFee", "type": "uint256", "internalType": "uint256" }, + ], + "outputs": [], + "stateMutability": "nonpayable", + }, + { + "type": "function", + "name": "onSetInterestBatchManager", + "inputs": [{ + "name": "_params", + "type": "tuple", + "internalType": "struct ITroveManager.OnSetInterestBatchManagerParams", + "components": [ + { "name": "troveId", "type": "uint256", "internalType": "uint256" }, + { "name": "troveColl", "type": "uint256", "internalType": "uint256" }, + { "name": "troveDebt", "type": "uint256", "internalType": "uint256" }, + { + "name": "troveChange", + "type": "tuple", + "internalType": "struct TroveChange", + "components": [ + { "name": "appliedRedistBoldDebtGain", "type": "uint256", "internalType": "uint256" }, + { "name": "appliedRedistCollGain", "type": "uint256", "internalType": "uint256" }, + { "name": "collIncrease", "type": "uint256", "internalType": "uint256" }, + { "name": "collDecrease", "type": "uint256", "internalType": "uint256" }, + { "name": "debtIncrease", "type": "uint256", "internalType": "uint256" }, + { "name": "debtDecrease", "type": "uint256", "internalType": "uint256" }, + { "name": "newWeightedRecordedDebt", "type": "uint256", "internalType": "uint256" }, + { "name": "oldWeightedRecordedDebt", "type": "uint256", "internalType": "uint256" }, + { "name": "upfrontFee", "type": "uint256", "internalType": "uint256" }, + { "name": "batchAccruedManagementFee", "type": "uint256", "internalType": "uint256" }, + { "name": "newWeightedRecordedBatchManagementFee", "type": "uint256", "internalType": "uint256" }, + { "name": "oldWeightedRecordedBatchManagementFee", "type": "uint256", "internalType": "uint256" }, + ], + }, + { "name": "newBatchAddress", "type": "address", "internalType": "address" }, + { "name": "newBatchColl", "type": "uint256", "internalType": "uint256" }, + { "name": "newBatchDebt", "type": "uint256", "internalType": "uint256" }, + ], + }], + "outputs": [], + "stateMutability": "nonpayable", }, { "type": "function", @@ -593,64 +520,6 @@ export const TroveManager = [ }], "stateMutability": "view", }, - { - "type": "function", - "name": "safeTransferFrom", - "inputs": [{ "name": "from", "type": "address", "internalType": "address" }, { - "name": "to", - "type": "address", - "internalType": "address", - }, { "name": "tokenId", "type": "uint256", "internalType": "uint256" }], - "outputs": [], - "stateMutability": "nonpayable", - }, - { - "type": "function", - "name": "safeTransferFrom", - "inputs": [ - { "name": "from", "type": "address", "internalType": "address" }, - { "name": "to", "type": "address", "internalType": "address" }, - { "name": "tokenId", "type": "uint256", "internalType": "uint256" }, - { "name": "data", "type": "bytes", "internalType": "bytes" }, - ], - "outputs": [], - "stateMutability": "nonpayable", - }, - { - "type": "function", - "name": "setAddresses", - "inputs": [ - { "name": "_borrowerOperationsAddress", "type": "address", "internalType": "address" }, - { "name": "_activePoolAddress", "type": "address", "internalType": "address" }, - { "name": "_defaultPoolAddress", "type": "address", "internalType": "address" }, - { "name": "_stabilityPoolAddress", "type": "address", "internalType": "address" }, - { "name": "_gasPoolAddress", "type": "address", "internalType": "address" }, - { "name": "_collSurplusPoolAddress", "type": "address", "internalType": "address" }, - { "name": "_priceFeedAddress", "type": "address", "internalType": "address" }, - { "name": "_boldTokenAddress", "type": "address", "internalType": "address" }, - { "name": "_sortedTrovesAddress", "type": "address", "internalType": "address" }, - ], - "outputs": [], - "stateMutability": "nonpayable", - }, - { - "type": "function", - "name": "setApprovalForAll", - "inputs": [{ "name": "operator", "type": "address", "internalType": "address" }, { - "name": "approved", - "type": "bool", - "internalType": "bool", - }], - "outputs": [], - "stateMutability": "nonpayable", - }, - { - "type": "function", - "name": "setCollateralRegistry", - "inputs": [{ "name": "_collateralRegistryAddress", "type": "address", "internalType": "address" }], - "outputs": [], - "stateMutability": "nonpayable", - }, { "type": "function", "name": "setTroveStatusToActive", @@ -682,57 +551,11 @@ export const TroveManager = [ }, { "type": "function", - "name": "supportsInterface", - "inputs": [{ "name": "interfaceId", "type": "bytes4", "internalType": "bytes4" }], - "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }], - "stateMutability": "view", - }, - { - "type": "function", - "name": "symbol", - "inputs": [], - "outputs": [{ "name": "", "type": "string", "internalType": "string" }], - "stateMutability": "view", - }, - { - "type": "function", - "name": "tokenURI", - "inputs": [{ "name": "tokenId", "type": "uint256", "internalType": "uint256" }], - "outputs": [{ "name": "", "type": "string", "internalType": "string" }], - "stateMutability": "view", - }, - { - "type": "function", - "name": "totalCollateralSnapshot", + "name": "troveNFT", "inputs": [], - "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], + "outputs": [{ "name": "", "type": "address", "internalType": "contract ITroveNFT" }], "stateMutability": "view", }, - { - "type": "function", - "name": "totalStakes", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], - "stateMutability": "view", - }, - { - "type": "function", - "name": "totalStakesSnapshot", - "inputs": [], - "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], - "stateMutability": "view", - }, - { - "type": "function", - "name": "transferFrom", - "inputs": [{ "name": "from", "type": "address", "internalType": "address" }, { - "name": "to", - "type": "address", - "internalType": "address", - }, { "name": "tokenId", "type": "uint256", "internalType": "uint256" }], - "outputs": [], - "stateMutability": "nonpayable", - }, { "type": "function", "name": "urgentRedemption", @@ -747,29 +570,36 @@ export const TroveManager = [ { "type": "event", "name": "ActivePoolAddressChanged", - "inputs": [{ "name": "_activePoolAddress", "type": "address", "indexed": false, "internalType": "address" }], + "inputs": [{ "name": "_newActivePoolAddress", "type": "address", "indexed": false, "internalType": "address" }], "anonymous": false, }, { "type": "event", - "name": "Approval", - "inputs": [{ "name": "owner", "type": "address", "indexed": true, "internalType": "address" }, { - "name": "approved", - "type": "address", - "indexed": true, - "internalType": "address", - }, { "name": "tokenId", "type": "uint256", "indexed": true, "internalType": "uint256" }], + "name": "BatchUpdated", + "inputs": [ + { "name": "_interestBatchManager", "type": "address", "indexed": true, "internalType": "address" }, + { "name": "_operation", "type": "uint8", "indexed": false, "internalType": "enum ITroveEvents.BatchOperation" }, + { "name": "_debt", "type": "uint256", "indexed": false, "internalType": "uint256" }, + { "name": "_coll", "type": "uint256", "indexed": false, "internalType": "uint256" }, + { "name": "_annualInterestRate", "type": "uint256", "indexed": false, "internalType": "uint256" }, + { "name": "_annualManagementFee", "type": "uint256", "indexed": false, "internalType": "uint256" }, + { "name": "_totalDebtShares", "type": "uint256", "indexed": false, "internalType": "uint256" }, + { "name": "_debtIncreaseFromUpfrontFee", "type": "uint256", "indexed": false, "internalType": "uint256" }, + ], "anonymous": false, }, { "type": "event", - "name": "ApprovalForAll", - "inputs": [{ "name": "owner", "type": "address", "indexed": true, "internalType": "address" }, { - "name": "operator", - "type": "address", - "indexed": true, - "internalType": "address", - }, { "name": "approved", "type": "bool", "indexed": false, "internalType": "bool" }], + "name": "BatchedTroveUpdated", + "inputs": [ + { "name": "_troveId", "type": "uint256", "indexed": true, "internalType": "uint256" }, + { "name": "_interestBatchManager", "type": "address", "indexed": false, "internalType": "address" }, + { "name": "_batchDebtShares", "type": "uint256", "indexed": false, "internalType": "uint256" }, + { "name": "_coll", "type": "uint256", "indexed": false, "internalType": "uint256" }, + { "name": "_stake", "type": "uint256", "indexed": false, "internalType": "uint256" }, + { "name": "_snapshotOfTotalCollRedist", "type": "uint256", "indexed": false, "internalType": "uint256" }, + { "name": "_snapshotOfTotalDebtRedist", "type": "uint256", "indexed": false, "internalType": "uint256" }, + ], "anonymous": false, }, { @@ -809,7 +639,7 @@ export const TroveManager = [ { "type": "event", "name": "DefaultPoolAddressChanged", - "inputs": [{ "name": "_defaultPoolAddress", "type": "address", "indexed": false, "internalType": "address" }], + "inputs": [{ "name": "_newDefaultPoolAddress", "type": "address", "indexed": false, "internalType": "address" }], "anonymous": false, }, { @@ -835,17 +665,6 @@ export const TroveManager = [ ], "anonymous": false, }, - { - "type": "event", - "name": "OwnershipTransferred", - "inputs": [{ "name": "previousOwner", "type": "address", "indexed": true, "internalType": "address" }, { - "name": "newOwner", - "type": "address", - "indexed": true, - "internalType": "address", - }], - "anonymous": false, - }, { "type": "event", "name": "PriceFeedAddressChanged", @@ -889,13 +708,8 @@ export const TroveManager = [ }, { "type": "event", - "name": "Transfer", - "inputs": [{ "name": "from", "type": "address", "indexed": true, "internalType": "address" }, { - "name": "to", - "type": "address", - "indexed": true, - "internalType": "address", - }, { "name": "tokenId", "type": "uint256", "indexed": true, "internalType": "uint256" }], + "name": "TroveNFTAddressChanged", + "inputs": [{ "name": "_newTroveNFTAddress", "type": "address", "indexed": false, "internalType": "address" }], "anonymous": false, }, { @@ -922,9 +736,21 @@ export const TroveManager = [ { "name": "_coll", "type": "uint256", "indexed": false, "internalType": "uint256" }, { "name": "_stake", "type": "uint256", "indexed": false, "internalType": "uint256" }, { "name": "_annualInterestRate", "type": "uint256", "indexed": false, "internalType": "uint256" }, - { "name": "_snapshotOfTotalDebtRedist", "type": "uint256", "indexed": false, "internalType": "uint256" }, { "name": "_snapshotOfTotalCollRedist", "type": "uint256", "indexed": false, "internalType": "uint256" }, + { "name": "_snapshotOfTotalDebtRedist", "type": "uint256", "indexed": false, "internalType": "uint256" }, ], "anonymous": false, }, + { "type": "error", "name": "CallerNotBorrowerOperations", "inputs": [] }, + { "type": "error", "name": "CallerNotCollateralRegistry", "inputs": [] }, + { "type": "error", "name": "EmptyData", "inputs": [] }, + { + "type": "error", + "name": "MinCollNotReached", + "inputs": [{ "name": "_coll", "type": "uint256", "internalType": "uint256" }], + }, + { "type": "error", "name": "NotEnoughBoldBalance", "inputs": [] }, + { "type": "error", "name": "NotShutDown", "inputs": [] }, + { "type": "error", "name": "NothingToLiquidate", "inputs": [] }, + { "type": "error", "name": "OnlyOneTroveLeft", "inputs": [] }, ] as const; diff --git a/frontend/app/src/abi/WETH.ts b/frontend/app/src/abi/WETH.ts new file mode 100644 index 00000000..202941a6 --- /dev/null +++ b/frontend/app/src/abi/WETH.ts @@ -0,0 +1,136 @@ +// this file was generated by scripts/update-liquity-abis.ts +// please do not edit it manually +export const WETH = [ + { "type": "receive", "stateMutability": "payable" }, + { + "type": "function", + "name": "allowance", + "inputs": [{ "name": "", "type": "address", "internalType": "address" }, { + "name": "", + "type": "address", + "internalType": "address", + }], + "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], + "stateMutability": "view", + }, + { + "type": "function", + "name": "approve", + "inputs": [{ "name": "guy", "type": "address", "internalType": "address" }, { + "name": "wad", + "type": "uint256", + "internalType": "uint256", + }], + "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }], + "stateMutability": "nonpayable", + }, + { + "type": "function", + "name": "balanceOf", + "inputs": [{ "name": "", "type": "address", "internalType": "address" }], + "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], + "stateMutability": "view", + }, + { + "type": "function", + "name": "decimals", + "inputs": [], + "outputs": [{ "name": "", "type": "uint8", "internalType": "uint8" }], + "stateMutability": "view", + }, + { "type": "function", "name": "deposit", "inputs": [], "outputs": [], "stateMutability": "payable" }, + { + "type": "function", + "name": "name", + "inputs": [], + "outputs": [{ "name": "", "type": "string", "internalType": "string" }], + "stateMutability": "view", + }, + { + "type": "function", + "name": "symbol", + "inputs": [], + "outputs": [{ "name": "", "type": "string", "internalType": "string" }], + "stateMutability": "view", + }, + { + "type": "function", + "name": "totalSupply", + "inputs": [], + "outputs": [{ "name": "", "type": "uint256", "internalType": "uint256" }], + "stateMutability": "view", + }, + { + "type": "function", + "name": "transfer", + "inputs": [{ "name": "dst", "type": "address", "internalType": "address" }, { + "name": "wad", + "type": "uint256", + "internalType": "uint256", + }], + "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }], + "stateMutability": "nonpayable", + }, + { + "type": "function", + "name": "transferFrom", + "inputs": [{ "name": "src", "type": "address", "internalType": "address" }, { + "name": "dst", + "type": "address", + "internalType": "address", + }, { "name": "wad", "type": "uint256", "internalType": "uint256" }], + "outputs": [{ "name": "", "type": "bool", "internalType": "bool" }], + "stateMutability": "nonpayable", + }, + { + "type": "function", + "name": "withdraw", + "inputs": [{ "name": "wad", "type": "uint256", "internalType": "uint256" }], + "outputs": [], + "stateMutability": "nonpayable", + }, + { + "type": "event", + "name": "Approval", + "inputs": [{ "name": "owner", "type": "address", "indexed": true, "internalType": "address" }, { + "name": "spender", + "type": "address", + "indexed": true, + "internalType": "address", + }, { "name": "value", "type": "uint256", "indexed": false, "internalType": "uint256" }], + "anonymous": false, + }, + { + "type": "event", + "name": "Deposit", + "inputs": [{ "name": "dst", "type": "address", "indexed": true, "internalType": "address" }, { + "name": "wad", + "type": "uint256", + "indexed": false, + "internalType": "uint256", + }], + "anonymous": false, + }, + { + "type": "event", + "name": "Transfer", + "inputs": [{ "name": "from", "type": "address", "indexed": true, "internalType": "address" }, { + "name": "to", + "type": "address", + "indexed": true, + "internalType": "address", + }, { "name": "value", "type": "uint256", "indexed": false, "internalType": "uint256" }], + "anonymous": false, + }, + { + "type": "event", + "name": "Withdrawal", + "inputs": [{ "name": "src", "type": "address", "indexed": true, "internalType": "address" }, { + "name": "wad", + "type": "uint256", + "indexed": false, + "internalType": "uint256", + }], + "anonymous": false, + }, +] as const; diff --git a/frontend/app/src/app/earn/page.tsx b/frontend/app/src/app/earn/page.tsx index 0a6f415a..144536fe 100644 --- a/frontend/app/src/app/earn/page.tsx +++ b/frontend/app/src/app/earn/page.tsx @@ -1,5 +1,3 @@ -"use client"; - import { EarnPoolsListScreen } from "@/src/screens/EarnPoolsListScreen/EarnPoolsListScreen"; export default function Page() { diff --git a/frontend/app/src/app/not-found.tsx b/frontend/app/src/app/not-found.tsx index 90730f78..1b779a35 100644 --- a/frontend/app/src/app/not-found.tsx +++ b/frontend/app/src/app/not-found.tsx @@ -1,6 +1,16 @@ +import { css } from "@/styled-system/css"; + export default function NotFoundPage() { return ( -
+
Not Found
); diff --git a/frontend/app/src/app/transactions/page.tsx b/frontend/app/src/app/transactions/page.tsx new file mode 100644 index 00000000..62e6a019 --- /dev/null +++ b/frontend/app/src/app/transactions/page.tsx @@ -0,0 +1,5 @@ +import { TransactionsScreen } from "@/src/screens/TransactionsScreen/TransactionsScreen"; + +export default function Page() { + return ; +} diff --git a/frontend/app/src/comps/Positions/NewPositionCard.tsx b/frontend/app/src/comps/Positions/NewPositionCard.tsx new file mode 100644 index 00000000..4bd0fb59 --- /dev/null +++ b/frontend/app/src/comps/Positions/NewPositionCard.tsx @@ -0,0 +1,243 @@ +import { ActionIcon } from "@/src/comps/ActionCard/ActionIcon"; +import content from "@/src/content"; +import { css } from "@/styled-system/css"; +import { token } from "@/styled-system/tokens"; +import { lerp } from "@liquity2/uikit"; +import { a, useSpring } from "@react-spring/web"; +import Link from "next/link"; +import { useEffect, useRef, useState } from "react"; + +const contentActions = content.home.actions; +const actionAttributes = { + borrow: { + colors: { + background: token("colors.brandDarkBlue"), + foreground: token("colors.brandDarkBlueContent"), + foregroundAlt: token("colors.strongSurfaceContentAlt"), + }, + description: contentActions.borrow.description, + path: "/borrow", + title: "Borrow", + }, + leverage: { + colors: { + background: token("colors.brandGreen"), + foreground: token("colors.brandGreenContent"), + foregroundAlt: token("colors.brandGreenContentAlt"), + }, + description: contentActions.leverage.description, + path: "/leverage", + title: "Leverage", + }, + earn: { + colors: { + background: token("colors.brandBlue"), + foreground: token("colors.brandBlueContent"), + foregroundAlt: token("colors.brandBlueContentAlt"), + }, + description: contentActions.earn.description, + path: "/earn", + title: "Earn", + }, + stake: { + colors: { + background: token("colors.brandGolden"), + foreground: token("colors.brandGoldenContent"), + foregroundAlt: token("colors.brandGoldenContentAlt"), + }, + description: contentActions.stake.description, + path: "/stake", + title: "Stake", + }, +} as const; + +const RESET_DELAY = 500; +const COMPRESSED_WIDTH = 28; +const ANIMATE_ICONS = true; + +export function NewPositionCard() { + const [hovered, setHovered_] = useState(-1); + + const delayedSetHovered = useRef>(); + const setHovered = (index: number, delay: number = 0) => { + clearTimeout(delayedSetHovered.current); + delayedSetHovered.current = setTimeout(() => { + setHovered_(index); + }, delay); + }; + useEffect(() => () => { + clearTimeout(delayedSetHovered.current); + }, []); + + const spring = useSpring({ + from: { + hovered0: 0, + hovered1: 0, + hovered2: 0, + hovered3: 0, + + compressed0: 0, + compressed1: 0, + compressed2: 0, + compressed3: 0, + + gridTemplateColumns: "25% 25% 25% 25%", + }, + to: { + hovered0: hovered === 0 ? 1 : 0, + hovered1: hovered === 1 ? 1 : 0, + hovered2: hovered === 2 ? 1 : 0, + hovered3: hovered === 3 ? 1 : 0, + + compressed0: hovered !== -1 && hovered !== 0 ? 1 : 0, + compressed1: hovered !== -1 && hovered !== 1 ? 1 : 0, + compressed2: hovered !== -1 && hovered !== 2 ? 1 : 0, + compressed3: hovered !== -1 && hovered !== 3 ? 1 : 0, + + gridTemplateColumns: Array.from({ length: 4 }).map((_, index) => ( + hovered === -1 + ? "25%" + : `${ + (hovered === index + ? (348 - (COMPRESSED_WIDTH * 3)) / 348 + : (COMPRESSED_WIDTH / 348)) * 100 + }%` + )).join(" "), + }, + config: { + mass: 1, + tension: 1800, + friction: 140, + }, + }); + + return ( +
+ + {Object.entries(actionAttributes).map(([type, { + description, + path, + title, + colors, + }], index) => { + const hprogress = spring[ + `hovered${index}` as keyof typeof spring + ] as typeof spring[`hovered${0 | 1 | 2 | 3}`]; + + const cprogress = spring[ + `compressed${index}` as keyof typeof spring + ] as typeof spring[`compressed${0 | 1 | 2 | 3}`]; + + const content = ( +
+ 1 - p), + left: hprogress.to((p) => lerp(8, 12, p)), + bottom: hprogress.to((p) => lerp(12, 80, p)), + transformOrigin: "0% 100%", + transform: hprogress.to( + [0, 0.5, 1], + [0, 1, 1], + ).to((p) => ` + rotate(${(1 - p) * -90}deg) + translateY(${(1 - p) * 100}%) + `), + }} + > + {title} + + ` + translateY(${(1 - p) * 20}px) + `), + opacity: hprogress.to([0, 0.9, 1], [0, 0, 1]), + color: colors.foregroundAlt, + }} + > + {description} + + 1 - p), + }} + > + + +
+ ); + + const className = css({ + position: "relative", + overflow: "hidden", + display: "flex", + flexDirection: "column", + _focusVisible: { + outline: "2px solid token(colors.focused)", + outlineOffset: 2, + }, + }); + + const style = { + zIndex: index === hovered ? 1 : 0, + background: colors.background, + color: colors.foreground, + borderRadius: index === 0 ? "8px 0 0 8px" : index === 3 ? "0 8px 8px 0" : 0, + }; + + return ( + setHovered(index)} + onMouseLeave={() => setHovered(-1, RESET_DELAY)} + onFocus={() => setHovered(index)} + onBlur={() => setHovered(-1)} + className={className} + style={style} + > + {content} + + ); + })} +
+
+ ); +} diff --git a/frontend/app/src/comps/Positions/Positions.tsx b/frontend/app/src/comps/Positions/Positions.tsx index b729804a..1de8a133 100644 --- a/frontend/app/src/comps/Positions/Positions.tsx +++ b/frontend/app/src/comps/Positions/Positions.tsx @@ -7,11 +7,13 @@ import content from "@/src/content"; import { ACCOUNT_POSITIONS } from "@/src/demo-mode"; import { DEMO_MODE } from "@/src/env"; import { formatLiquidationRisk, formatRedemptionRisk } from "@/src/formatting"; +import { fmtnum } from "@/src/formatting"; import { getLiquidationRisk, getLtv, getRedemptionRisk } from "@/src/liquity-math"; import { useAccount } from "@/src/services/Ethereum"; import { usePrice } from "@/src/services/Prices"; import { useLoansByAccount } from "@/src/subgraph-hooks"; import { riskLevelToStatusMode } from "@/src/uikit-utils"; +import { sleep } from "@/src/utils"; import { css } from "@/styled-system/css"; import { HFlex, @@ -26,72 +28,81 @@ import { TOKENS_BY_SYMBOL, } from "@liquity2/uikit"; import { a, useTransition } from "@react-spring/web"; +import { useQuery } from "@tanstack/react-query"; import * as dn from "dnum"; import Link from "next/link"; -import { useState } from "react"; import { match } from "ts-pattern"; +import { NewPositionCard } from "./NewPositionCard"; + +type Mode = "positions" | "loading" | "actions"; export function Positions() { const account = useAccount(); const loans = useLoansByAccount(account.address); - const positions = DEMO_MODE ? ACCOUNT_POSITIONS : loans.data ?? []; - - const positionCards = positions.map((position, index) => ( - match(position) - .with({ type: "borrow" }, ({ type, ...props }) => [index, ]) - .with({ type: "earn" }, ({ type, ...props }) => [index, ]) - .with({ type: "leverage" }, ({ type, ...props }) => [index, ]) - .with({ type: "stake" }, ({ type, ...props }) => [index, ]) - .exhaustive() - )); + const positions = useQuery({ + enabled: account.isConnected && !loans.isLoading, + queryKey: ["CombinedPositions", account.address], + queryFn: async () => { + await sleep(300); + return DEMO_MODE ? ACCOUNT_POSITIONS : loans.data ?? []; + }, + }); - const mode = account.isConnected && (positionCards.length > 0 || loans.isLoading) ? "positions" : "actions"; + const positionsLoading = loans.isLoading || positions.isLoading; - const actionCards = [ - , - , - , - , - ].map((card, index) => [index, card]); + let mode: Mode = account.isConnected && positions.data && positions.data.length > 0 + ? "positions" + : positionsLoading + ? "loading" + : "actions"; - const [increment, setIncrement] = useState(0); + const cards = match(mode) + .returnType>() + .with("positions", () => [ + ...(positions.data?.map((position, index) => ( + match(position) + .returnType<[number, ReactNode]>() + .with({ type: "borrow" }, (props) => [index, ]) + .with({ type: "earn" }, (props) => [index, ]) + .with({ type: "leverage" }, (props) => [index, ]) + .with({ type: "stake" }, (props) => [index, ]) + .exhaustive() + )) ?? []), + [positions.data?.length ?? -1, ], + ]) + .with("loading", () => [ + [0, ], + [1, ], + [2, ], + ]) + .otherwise(() => [ + [0, ], + [1, ], + [2, ], + [3, ], + ]); - const positionTransitions = useTransition( - mode === "positions" ? positionCards : actionCards, - { - keys: ([index]) => `${index}${mode}${increment}`, - from: { opacity: 0, transform: "scale3d(0.95, 0.95, 1)" }, - enter: { opacity: 1, transform: "scale3d(1, 1, 1)" }, - leave: { display: "none", immediate: true }, - trail: 10, - config: { - mass: 1, - tension: 2800, - friction: 80, - }, + const positionTransitions = useTransition(cards, { + keys: ([index]) => `${mode}${index}`, + from: { opacity: 0, transform: "scale3d(0.97, 0.97, 1)" }, + enter: { opacity: 1, transform: "scale3d(1, 1, 1)" }, + leave: { display: "none", immediate: true }, + config: { + mass: 2, + tension: 1800, + friction: 80, }, - ); - - const [forceLoading, setForceLoading] = useState(false); + }); return ( - { - setForceLoading(true); - setTimeout(() => { - setForceLoading(false); - setIncrement((i) => i + 1); - }, 1000); - }} - > + {positionTransitions((style, [_, card]) => ( @@ -104,34 +115,23 @@ export function Positions() { function PositionsGroup({ children, - loading, mode, onTitleClick, }: { children: ReactNode; - loading?: boolean; - mode: "positions" | "actions"; + mode: Mode; onTitleClick?: () => void; }) { - const loadingTransition = useTransition(loading, { - from: { - opacity: 0, - transform: "scale3d(0.95, 0.95, 1)", - }, - enter: { - opacity: 1, - transform: "scale3d(1, 1, 1)", - }, - leave: { - opacity: 0, - transform: "scale3d(0.95, 0.95, 1)", - }, - config: { - mass: 1, - tension: 1800, - friction: 80, - }, - }); + const paddingBottom = mode === "actions" ? 48 : 32; + + const title = mode === "actions" + ? content.home.openPositionTitle + : content.home.myPositionsTitle; + + const cardsHeight = mode === "actions" ? undefined : 185; + + const columns = mode === "actions" ? 4 : 3; + return (

- {mode === "positions" ? content.home.myPositionsTitle : content.home.openPositionTitle} + {title}

- {loadingTransition((style, loading) => ( - loading && ( - -
-
- Fetching positions… -
- - ) - ))} - {!loading && ( -
- {children} -
- )} +
+ {children} +
); @@ -208,6 +174,7 @@ function PositionsGroup({ function PositionBorrow({ borrowed, + collIndex, collateral, deposit, interestRate, @@ -215,6 +182,7 @@ function PositionBorrow({ }: Pick< PositionLoan, | "borrowed" + | "collIndex" | "collateral" | "deposit" | "interestRate" @@ -233,17 +201,21 @@ function PositionBorrow({ const maxLtv = dn.from(1 / token.collateralRatio, 18); const liquidationRisk = ltv && getLiquidationRisk(ltv, maxLtv); + const title = [ + `Loan ID: ${troveId}`, + `Borrowed: ${fmtnum(borrowed, "full")} BOLD`, + `Collateral: ${fmtnum(deposit, "full")} ${token.name}`, + `Interest rate: ${fmtnum(interestRate, "full", 100)}%`, + ]; + return ( - {dn.format(dn.add(deposit, borrowed), 2)} + {fmtnum(borrowed)} @@ -830,6 +803,17 @@ function PositionStake({ ); } +function LoadingCard() { + return ( + + ); +} + function EditSquare() { return (
`rotate(${r}deg)`), + }} + > + + + ); +} diff --git a/frontend/app/src/constants.ts b/frontend/app/src/constants.ts index d41c0e5a..d3fbc848 100644 --- a/frontend/app/src/constants.ts +++ b/frontend/app/src/constants.ts @@ -4,7 +4,6 @@ import type { RiskLevel } from "@/src/types"; import { norm } from "@liquity2/uikit"; import * as dn from "dnum"; -import * as v from "valibot"; export const APP_TITLE = "Liquity v2"; export const LOCAL_STORAGE_PREFIX = "liquity2:"; @@ -14,12 +13,6 @@ export const MAX_LTV_ALLOWED = 0.916; // ratio of the max LTV allowed by the app export const ETH_MAX_RESERVE = dn.from(0.1, 18); // leave 0.1 ETH when users click on "max" to deposit from their account export const ETH_GAS_COMPENSATION = dn.from(0.0375, 18); // see contracts/src/Dependencies/Constants.sol -export const CollateralIdSchema = v.union([ - v.literal("ETH"), - v.literal("STETH"), - v.literal("RETH"), -]); - export const LQTY_SUPPLY = dn.from(100_000_000, 18); export const INTEREST_RATE_MIN = 1; diff --git a/frontend/app/src/contracts.ts b/frontend/app/src/contracts.ts index 05b06a94..353bc464 100644 --- a/frontend/app/src/contracts.ts +++ b/frontend/app/src/contracts.ts @@ -11,6 +11,7 @@ import { PriceFeed } from "@/src/abi/PriceFeed"; import { SortedTroves } from "@/src/abi/SortedTroves"; import { StabilityPool } from "@/src/abi/StabilityPool"; import { TroveManager } from "@/src/abi/TroveManager"; +import { WETH } from "@/src/abi/WETH"; import { COLLATERAL_CONTRACTS, CONTRACT_BOLD_TOKEN, @@ -27,7 +28,7 @@ const protocolAbis = { CollateralRegistry, HintHelpers, MultiTroveGetter, - WETH: erc20Abi, + WETH, } as const; const collateralAbis = { @@ -60,7 +61,10 @@ type Contract = { type CollateralContracts = Record>; -type Collaterals = Array<[keyof typeof COLLATERAL_CONTRACTS, CollateralContracts]>; +type Collaterals = Array<{ + symbol: CollateralSymbol; + contracts: CollateralContracts; +}>; type Contracts = { [K in (ProtocolContractName | "collaterals")]: K extends "collaterals" ? Collaterals @@ -68,23 +72,6 @@ type Contracts = { : never; }; -function collateralAddressesToContracts( - collateral: typeof COLLATERAL_CONTRACTS[keyof typeof COLLATERAL_CONTRACTS], -): CollateralContracts | null { - return collateral - ? { - ActivePool: { abi: abis.ActivePool, address: collateral.ACTIVE_POOL }, - BorrowerOperations: { abi: abis.BorrowerOperations, address: collateral.BORROWER_OPERATIONS }, - DefaultPool: { abi: abis.DefaultPool, address: collateral.DEFAULT_POOL }, - PriceFeed: { abi: abis.PriceFeed, address: collateral.PRICE_FEED }, - SortedTroves: { abi: abis.SortedTroves, address: collateral.SORTED_TROVES }, - StabilityPool: { abi: abis.StabilityPool, address: collateral.STABILITY_POOL }, - Token: { abi: abis.Token, address: collateral.TOKEN }, - TroveManager: { abi: abis.TroveManager, address: collateral.TROVE_MANAGER }, - } - : null; -} - // Note: even though the contracts related data is coming from the environment, // hooks are being used so that we could later change these at runtime. export function useContracts(): Contracts { @@ -95,14 +82,25 @@ export function useContracts(): Contracts { HintHelpers: { abi: abis.HintHelpers, address: CONTRACT_HINT_HELPERS }, MultiTroveGetter: { abi: abis.MultiTroveGetter, address: CONTRACT_MULTI_TROVE_GETTER }, WETH: { abi: abis.WETH, address: CONTRACT_WETH }, - collaterals: Object.entries(COLLATERAL_CONTRACTS).map(([symbol, collateral]) => [ + collaterals: COLLATERAL_CONTRACTS.map(({ symbol, contracts }) => ({ symbol, - collateralAddressesToContracts(collateral), - ]) as Collaterals, + contracts: { + ActivePool: { address: contracts.ACTIVE_POOL, abi: abis.ActivePool }, + BorrowerOperations: { address: contracts.BORROWER_OPERATIONS, abi: abis.BorrowerOperations }, + DefaultPool: { address: contracts.DEFAULT_POOL, abi: abis.DefaultPool }, + PriceFeed: { address: contracts.PRICE_FEED, abi: abis.PriceFeed }, + SortedTroves: { address: contracts.SORTED_TROVES, abi: abis.SortedTroves }, + StabilityPool: { address: contracts.STABILITY_POOL, abi: abis.StabilityPool }, + Token: { address: contracts.TOKEN, abi: abis.Token }, + TroveManager: { address: contracts.TROVE_MANAGER, abi: abis.TroveManager }, + }, + })), }; }, []); } +export const useCollateralContracts = () => useContracts().collaterals; + export function useProtocolContract(name: ProtocolContractName): Contract { return useContracts()[name]; } @@ -112,24 +110,12 @@ export function useCollateralContract( name: CollateralContractName, ): Contract | null { const { collaterals } = useContracts(); - return getCollateralContracts(symbol, collaterals)?.[name] ?? null; -} - -export function useAvailableCollaterals(): CollateralSymbol[] { - return Object.keys(useContracts().collaterals) as CollateralSymbol[]; -} - -export function findCollateralIndex(symbol: CollateralSymbol, collaterals: Collaterals): number { - return collaterals.findIndex(([s]) => s === symbol); + return collaterals.find((c) => c.symbol === symbol)?.contracts?.[name] ?? null; } export function getCollateralContracts( - symbolOrIndex: CollateralSymbol | number, + symbolOrIndex: CollateralSymbol, collaterals: Collaterals, ): CollateralContracts | null { - return collaterals[ - typeof symbolOrIndex === "string" - ? findCollateralIndex(symbolOrIndex, collaterals) - : symbolOrIndex - ][1] ?? null; + return collaterals.find(({ symbol }) => symbol === symbolOrIndex)?.contracts ?? null; } diff --git a/frontend/app/src/demo-mode/demo-data.ts b/frontend/app/src/demo-mode/demo-data.ts index 3fb9d64f..322f08a6 100644 --- a/frontend/app/src/demo-mode/demo-data.ts +++ b/frontend/app/src/demo-mode/demo-data.ts @@ -5,6 +5,8 @@ import type { Dnum } from "dnum"; import { INTEREST_RATE_INCREMENT, INTEREST_RATE_MAX, INTEREST_RATE_MIN } from "@/src/constants"; import * as dn from "dnum"; +export const LOAN_SCREEN_MANUAL_LOADING_STATE = false; + export const PRICE_UPDATE_INTERVAL = 15_000; export const PRICE_UPDATE_VARIATION = 0.003; export const PRICE_UPDATE_MANUAL = false; @@ -29,6 +31,7 @@ export const ACCOUNT_BALANCES = { LQTY: dn.from(2008.217, 18), RETH: dn.from(1.3732, 18), STETH: dn.from(17.912, 18), + LUSD: dn.from(1_200, 18), } as const; export const ACCOUNT_POSITIONS: Position[] = [ @@ -39,6 +42,7 @@ export const ACCOUNT_POSITIONS: Position[] = [ deposit: dn.from(5.5, 18), interestRate: dn.from(0.067, 18), troveId: "0x01", + collIndex: 1, }, { type: "leverage", @@ -47,6 +51,7 @@ export const ACCOUNT_POSITIONS: Position[] = [ deposit: dn.from(19.20, 18), // 8 ETH @ 2.4 leverage interestRate: dn.from(0.045, 18), troveId: "0x02", + collIndex: 0, }, { type: "earn", diff --git a/frontend/app/src/env.ts b/frontend/app/src/env.ts index d325e2ab..37fe67c1 100644 --- a/frontend/app/src/env.ts +++ b/frontend/app/src/env.ts @@ -1,9 +1,14 @@ import type { Address } from "@/src/types"; -import { CollateralIdSchema } from "@/src/constants"; import { vAddress, vEnvAddressAndBlock, vEnvCurrency, vEnvFlag, vEnvLink } from "@/src/valibot-utils"; import * as v from "valibot"; +export const CollateralSymbolSchema = v.union([ + v.literal("ETH"), + v.literal("RETH"), + v.literal("STETH"), +]); + export const EnvSchema = v.pipe( v.object({ APP_VERSION: v.string(), @@ -26,6 +31,9 @@ export const EnvSchema = v.pipe( CHAIN_CONTRACT_MULTICALL: v.optional(vEnvAddressAndBlock()), COMMIT_HASH: v.string(), + LQTY_TOKEN: vAddress(), + LUSD_TOKEN: vAddress(), + CONTRACT_BOLD_TOKEN: vAddress(), CONTRACT_COLLATERAL_REGISTRY: vAddress(), CONTRACT_FUNCTION_CALLER: vAddress(), @@ -41,7 +49,7 @@ export const EnvSchema = v.pipe( COLL_0_CONTRACT_STABILITY_POOL: v.optional(vAddress()), COLL_0_CONTRACT_TOKEN: v.optional(vAddress()), COLL_0_CONTRACT_TROVE_MANAGER: v.optional(vAddress()), - COLL_0_TOKEN_ID: v.optional(CollateralIdSchema), + COLL_0_TOKEN_ID: v.optional(CollateralSymbolSchema), COLL_1_CONTRACT_ACTIVE_POOL: v.optional(vAddress()), COLL_1_CONTRACT_BORROWER_OPERATIONS: v.optional(vAddress()), @@ -51,7 +59,7 @@ export const EnvSchema = v.pipe( COLL_1_CONTRACT_STABILITY_POOL: v.optional(vAddress()), COLL_1_CONTRACT_TOKEN: v.optional(vAddress()), COLL_1_CONTRACT_TROVE_MANAGER: v.optional(vAddress()), - COLL_1_TOKEN_ID: v.optional(CollateralIdSchema), + COLL_1_TOKEN_ID: v.optional(CollateralSymbolSchema), COLL_2_CONTRACT_ACTIVE_POOL: v.optional(vAddress()), COLL_2_CONTRACT_BORROWER_OPERATIONS: v.optional(vAddress()), @@ -61,7 +69,7 @@ export const EnvSchema = v.pipe( COLL_2_CONTRACT_STABILITY_POOL: v.optional(vAddress()), COLL_2_CONTRACT_TOKEN: v.optional(vAddress()), COLL_2_CONTRACT_TROVE_MANAGER: v.optional(vAddress()), - COLL_2_TOKEN_ID: v.optional(CollateralIdSchema), + COLL_2_TOKEN_ID: v.optional(CollateralSymbolSchema), DEMO_MODE: vEnvFlag(), WALLET_CONNECT_PROJECT_ID: v.string(), @@ -82,18 +90,13 @@ export const EnvSchema = v.pipe( type ContractEnvName = typeof contractsEnvNames[number]; - const collateralContracts: Record< - v.InferOutput, - Record | null - > = { - ETH: null, - RETH: null, - STETH: null, - }; + const collateralContracts: Array<{ + symbol: v.InferOutput; + contracts: Record; + }> = []; for (const index of Array(10).keys()) { const collEnvName = `COLL_${index}`; - const contracts: Partial> = {}; for (const name of contractsEnvNames) { @@ -105,11 +108,17 @@ export const EnvSchema = v.pipe( } const contractsCount = Object.values(contracts).filter((v) => v).length; - if (contractsCount === contractsEnvNames.length) { - collateralContracts[ - env[`${collEnvName}_TOKEN_ID` as keyof typeof env] as v.InferOutput - ] = contracts as Record; + if (contractsCount === 0) { + break; } + if (contractsCount !== contractsEnvNames.length) { + throw new Error(`Incomplete contracts for collateral ${index}`); + } + + collateralContracts[index] = { + symbol: env[`${collEnvName}_TOKEN_ID` as keyof typeof env] as v.InferOutput, + contracts: contracts as Record, + }; } return { @@ -140,6 +149,9 @@ const parsedEnv = v.parse(EnvSchema, { CONTRACT_MULTI_TROVE_GETTER: process.env.NEXT_PUBLIC_CONTRACT_MULTI_TROVE_GETTER, CONTRACT_WETH: process.env.NEXT_PUBLIC_CONTRACT_WETH, + LQTY_TOKEN: process.env.NEXT_PUBLIC_LQTY_TOKEN, + LUSD_TOKEN: process.env.NEXT_PUBLIC_LUSD_TOKEN, + COLL_0_TOKEN_ID: process.env.NEXT_PUBLIC_COLL_0_TOKEN_ID, COLL_1_TOKEN_ID: process.env.NEXT_PUBLIC_COLL_1_TOKEN_ID, COLL_2_TOKEN_ID: process.env.NEXT_PUBLIC_COLL_2_TOKEN_ID, @@ -190,6 +202,8 @@ export const { CONTRACT_BOLD_TOKEN, CONTRACT_COLLATERAL_REGISTRY, CONTRACT_FUNCTION_CALLER, + LQTY_TOKEN, + LUSD_TOKEN, CONTRACT_HINT_HELPERS, CONTRACT_MULTI_TROVE_GETTER, CONTRACT_WETH, diff --git a/frontend/app/src/formatting.ts b/frontend/app/src/formatting.ts index 0f89c576..6b1a8fcc 100644 --- a/frontend/app/src/formatting.ts +++ b/frontend/app/src/formatting.ts @@ -16,13 +16,13 @@ function isDnFormatName(value: unknown): value is keyof typeof dnFormatOptions { } export function fmtnum( - value: Dnum | number | null, + value: Dnum | number | null | undefined, optionsOrFormatName: | keyof typeof dnFormatOptions | Parameters[1] = "2z", - scale = 1, + scale = 1, // pass 100 here to format as percentage ) { - if (value === null) { + if (value === null || value === undefined) { return ""; } if (typeof value === "number") { diff --git a/frontend/app/src/liquity-utils.ts b/frontend/app/src/liquity-utils.ts index 9143adcf..7dd8a3a5 100644 --- a/frontend/app/src/liquity-utils.ts +++ b/frontend/app/src/liquity-utils.ts @@ -1,17 +1,11 @@ -import type { TroveId } from "@/src/types"; -import type { Address, CollateralSymbol } from "@liquity2/uikit"; -import type { Dnum } from "dnum"; +import type { CollIndex, PrefixedTroveId, TroveId } from "@/src/types"; +import type { Address, CollateralSymbol, CollateralToken } from "@liquity2/uikit"; -import { useCollateralContract, useProtocolContract } from "@/src/contracts"; -import { ADDRESS_ZERO } from "@/src/eth-utils"; -import { useWatchQueries } from "@/src/wagmi-utils"; -import { useEffect, useState } from "react"; +import { useCollateralContracts } from "@/src/contracts"; +import { isCollIndex, isTroveId } from "@/src/types"; +import { COLLATERALS } from "@liquity2/uikit"; import { match } from "ts-pattern"; -import { encodeAbiParameters, keccak256, maxUint256, parseAbiParameters } from "viem"; -import { useAccount, useBalance, useReadContract, useReadContracts, useWriteContract } from "wagmi"; - -// TODO: make the collateral index dynamic -const collSymbol = "ETH" as const; +import { encodeAbiParameters, keccak256, parseAbiParameters } from "viem"; // As defined in ITroveManager.sol export type TroveStatus = @@ -21,26 +15,13 @@ export type TroveStatus = | "closedByLiquidation" | "unredeemable"; -type TroveDetails = { - status: TroveStatus; - stake: Dnum; - debt: Dnum; - collateral: Dnum; - interestRate: Dnum; -}; - -type Rewards = { - eth: Dnum; - bold: Dnum; -}; - export function shortenTroveId(troveId: TroveId, chars = 4) { return troveId.length < chars * 2 + 2 ? troveId : troveId.slice(0, chars + 2) + "…" + troveId.slice(-chars); } -function troveStatusFromNumber(value: number): TroveStatus { +export function troveStatusFromNumber(value: number): TroveStatus { return match(value) .with(0, () => "nonExistent") .with(1, () => "active") @@ -62,276 +43,6 @@ export function troveStatusToLabel(status: TroveStatus) { .exhaustive(); } -export function useTroveDetails(troveId: TroveId = 0n) { - const TroveManagerContract = useCollateralContract(collSymbol, "TroveManager"); - - const read = useReadContracts({ - allowFailure: false, - contracts: TroveManagerContract - ? [ - { - ...TroveManagerContract, - functionName: "getTroveStatus", - args: [troveId], - }, - { - ...TroveManagerContract, - functionName: "getTroveStake", - args: [troveId], - }, - { - ...TroveManagerContract, - functionName: "getTroveDebt", - args: [troveId], - }, - { - ...TroveManagerContract, - functionName: "getTroveColl", - args: [troveId], - }, - { - ...TroveManagerContract, - functionName: "getTroveAnnualInterestRate", - args: [troveId], - }, - ] - : [], - }); - - useWatchQueries([read]); - - if (!read.data || read.status !== "success") { - return { ...read, data: undefined }; - } - - const troveStatusNumber = Number(read.data[0]); - - const data: TroveDetails = { - status: troveStatusFromNumber(isNaN(troveStatusNumber) ? 0 : troveStatusNumber), - stake: [read.data[1] ?? 0n, 18], - debt: [read.data[2] ?? 0n, 18], - collateral: [read.data[3] ?? 0n, 18], - interestRate: [read.data[4] ?? 0n, 18], - }; - - return { ...read, data }; -} - -export function useFindAvailableTroveIndex(owner?: Address | null): - | { - data: number; - error: undefined; - status: "success"; - } - | { - data: undefined; - error: undefined; - status: "loading"; - } - | { - data: undefined; - error: Error; - status: "error"; - } - | { - data: undefined; - error: undefined; - status: "idle"; - } -{ - const [troveIndex, setTroveIndex] = useState(0); - - // reset trove search when owner changes - useEffect(() => { - if (owner) { - setTroveIndex(0); - } - }, [owner]); - - const TroveManagerContract = useCollateralContract(collSymbol, "TroveManager"); - - const read = useReadContract( - owner - ? { - ...TroveManagerContract, - functionName: "checkTroveIsOpen", - args: [getTroveId(owner, BigInt(troveIndex))], - } - : {}, - ); - - useWatchQueries([read]); - - if (owner === null || owner === undefined) { - return { - data: undefined, - error: undefined, - status: "idle", - }; - } - - if (read.data === true) { - setTroveIndex(troveIndex + 1); - return { - data: undefined, - error: undefined, - status: "loading", - }; - } - - if (read.data === false) { - return { - data: troveIndex, - error: undefined, - status: "success", - }; - } - - if (read.status === "error") { - return { - data: undefined, - error: read.error, - status: "error", - }; - } - - return { - data: undefined, - error: undefined, - status: "loading", - }; -} - -export function useOpenTrove(owner: Address, { - ownerIndex, - maxFeePercentage, - boldAmount, - upperHint, - lowerHint, - interestRate, - ethAmount, -}: { - ownerIndex: bigint; - maxFeePercentage: bigint; // 0 to 1 * 10^18 - boldAmount: bigint; // amount * 10^18 - upperHint: bigint; - lowerHint: bigint; - interestRate: bigint; // 0 to 1 * 10^18 - ethAmount: bigint; // amount * 10^18 -}) { - const { writeContract } = useWriteContract(); - - const BorrowerOperationsContract = useCollateralContract(collSymbol, "BorrowerOperations"); - - return () => { - if (BorrowerOperationsContract) { - writeContract({ - ...BorrowerOperationsContract, - functionName: "openTrove", - args: [ - owner, - ownerIndex, - maxFeePercentage, - ethAmount, - boldAmount, - upperHint, - lowerHint, - interestRate, - ], - }); - } - }; -} - -export function useCloseTrove(troveId: TroveId) { - const { writeContract } = useWriteContract(); - - const BorrowerOperationsContract = useCollateralContract(collSymbol, "BorrowerOperations"); - - return () => { - if (BorrowerOperationsContract) { - writeContract({ - ...BorrowerOperationsContract, - functionName: "closeTrove", - args: [troveId], - }); - } - }; -} - -export function useTroveRewards(troveId: TroveId) { - const TroveManagerContract = useCollateralContract(collSymbol, "TroveManager"); - - const read = useReadContracts({ - allowFailure: false, - contracts: TroveManagerContract - ? [ - { - ...TroveManagerContract, - functionName: "getPendingCollReward", - args: [troveId], - }, - { - ...TroveManagerContract, - functionName: "getPendingBoldDebtReward", - args: [troveId], - }, - ] - : [], - }); - useWatchQueries([read]); - - if (!read.data || read.status !== "success") { - return { - ...read, - data: undefined, - }; - } - - const data: Rewards = { - eth: [read.data[0] ?? 0n, 18], - bold: [read.data[1] ?? 0n, 18], - }; - - return { - ...read, - data, - }; -} - -export function useStabilityPoolStats() { - const StabilityPoolContract = useCollateralContract(collSymbol, "StabilityPool"); - - const read = useReadContracts({ - allowFailure: false, - contracts: [ - { - ...StabilityPoolContract, - functionName: "getTotalBoldDeposits", - }, - { - ...StabilityPoolContract, - functionName: "getCollBalance", - }, - ], - }); - useWatchQueries([read]); - - if (!read.data || read.status !== "success") { - return { - ...read, - data: undefined, - }; - } - - const data = { - totalBoldDeposits: [read.data[0], 18], - collBalance: [read.data[1], 18], - } as const; - - return { ...read, data }; -} - export function getTroveId(owner: Address, ownerIndex: bigint | number) { return BigInt(keccak256(encodeAbiParameters( parseAbiParameters("address, uint256"), @@ -354,71 +65,29 @@ export function getCollateralFromTroveSymbol(symbol: string): null | CollateralS return null; } -export function useCollTokenAllowance() { - const account = useAccount(); - - const BorrowerOperationsContract = useCollateralContract(collSymbol, "BorrowerOperations"); - const CollTokenContract = useProtocolContract("BoldToken"); - - const allowance = useReadContract({ - ...CollTokenContract, - functionName: "allowance", - args: [account.address ?? ADDRESS_ZERO, BorrowerOperationsContract?.address ?? ADDRESS_ZERO], - }); - useWatchQueries([allowance]); - - const collTokenWrite = useWriteContract(); - const approve = (amount = maxUint256) => ( - collTokenWrite.writeContract({ - ...CollTokenContract, - functionName: "approve", - args: [BorrowerOperationsContract?.address ?? ADDRESS_ZERO, amount], - }) - ); - - return { - allowance, - collTokenWrite, - approve, - } as const; +export function parsePrefixedTroveId(value: PrefixedTroveId): { + collIndex: CollIndex; + troveId: TroveId; +} { + const [collIndex_, troveId] = value.split(":"); + const collIndex = parseInt(collIndex_, 10); + if (!isCollIndex(collIndex) || !isTroveId(troveId)) { + throw new Error(`Invalid prefixed trove ID: ${value}`); + } + return { collIndex, troveId }; } -export function useAccountBalances(address: Address | undefined, updateInterval?: number) { - const ethBalance = useBalance({ - address: address ?? ADDRESS_ZERO, - query: { - select: ({ value }) => [value ?? 0n, 18] as const, - }, - }); - - const BoldTokenContract = useProtocolContract("BoldToken"); - const CollTokenContract = useCollateralContract(collSymbol, "Token"); - - const readTokenBalances = useReadContracts({ - contracts: [ - { - ...BoldTokenContract, - functionName: "balanceOf", - args: [address ?? ADDRESS_ZERO], - }, - { - ...CollTokenContract, - functionName: "balanceOf", - args: [address ?? ADDRESS_ZERO], - }, - ], - query: { - select: (data) => data.map(({ result }) => [result ?? 0n, 18] as const), - }, - }); - - useWatchQueries([ethBalance, readTokenBalances], updateInterval); +export function getPrefixedTroveId(collIndex: CollIndex, troveId: TroveId): PrefixedTroveId { + return `${collIndex}:${troveId}`; +} - return { - boldBalance: readTokenBalances.data?.[0], - collBalance: readTokenBalances.data?.[1], - error: ethBalance.error ?? readTokenBalances.error, - ethBalance: ethBalance.data, - status: ethBalance.status === "success" ? readTokenBalances.status : ethBalance.status, - }; +export function useCollateral(collIndex: number): CollateralToken { + const collContracts = useCollateralContracts(); + return collContracts.map(({ symbol }) => { + const collateral = COLLATERALS.find((c) => c.symbol === symbol); + if (!collateral) { + throw new Error(`Unknown collateral symbol: ${symbol}`); + } + return collateral; + })[collIndex]; } diff --git a/frontend/app/src/screens/BorrowScreen/BorrowScreen.tsx b/frontend/app/src/screens/BorrowScreen/BorrowScreen.tsx index 988c6e85..5f2e7f75 100644 --- a/frontend/app/src/screens/BorrowScreen/BorrowScreen.tsx +++ b/frontend/app/src/screens/BorrowScreen/BorrowScreen.tsx @@ -7,18 +7,21 @@ import { RedemptionInfo } from "@/src/comps/RedemptionInfo/RedemptionInfo"; import { Screen } from "@/src/comps/Screen/Screen"; import { DEBT_SUGGESTIONS, INTEREST_RATE_DEFAULT } from "@/src/constants"; import content from "@/src/content"; -import { ACCOUNT_BALANCES } from "@/src/demo-mode"; +import { useCollateralContracts } from "@/src/contracts"; +import { dnum18 } from "@/src/dnum-utils"; import { useInputFieldValue } from "@/src/form-utils"; +import { fmtnum } from "@/src/formatting"; import { getLiquidationRisk, getLoanDetails, getLtv } from "@/src/liquity-math"; -import { useFindAvailableTroveIndex } from "@/src/liquity-utils"; -import { useAccount } from "@/src/services/Ethereum"; +import { useAccount, useBalance } from "@/src/services/Ethereum"; import { usePrice } from "@/src/services/Prices"; import { useTransactionFlow } from "@/src/services/TransactionFlow"; +import { useTroveCount } from "@/src/subgraph-hooks"; +import { isCollIndex } from "@/src/types"; import { infoTooltipProps } from "@/src/uikit-utils"; import { css } from "@/styled-system/css"; import { Button, - COLLATERALS, + COLLATERALS as KNOWN_COLLATERALS, Dropdown, HFlex, IconSuggestion, @@ -32,41 +35,55 @@ import { import * as dn from "dnum"; import { useParams, useRouter } from "next/navigation"; import { useState } from "react"; -import { match, P } from "ts-pattern"; +import { maxUint256 } from "viem"; -const collateralSymbols = COLLATERALS.map(({ symbol }) => symbol); +const KNOWN_COLLATERAL_SYMBOLS = KNOWN_COLLATERALS.map(({ symbol }) => symbol); export function BorrowScreen() { - const account = useAccount(); - - const { - currentStepIndex, - discard, - signAndSend, - start, - flow, - } = useTransactionFlow(); - - const availableTroveIndex = useFindAvailableTroveIndex(account.address); - const openedTroveIndex = (availableTroveIndex.data ?? 0) - 1; - const router = useRouter(); - // useParams() can return an array, but not with the current - // routing setup so we can safely assume it’s a string - const collSymbol = String(useParams().collateral ?? "eth").toUpperCase(); + const account = useAccount(); + const txFlow = useTransactionFlow(); + const allCollContracts = useCollateralContracts(); + + // useParams() can return an array but not with the current + // routing setup, so we can safely cast it to a string + const collSymbol = String(useParams().collateral ?? allCollContracts[0].symbol).toUpperCase(); if (!isCollateralSymbol(collSymbol)) { throw new Error(`Invalid collateral symbol: ${collSymbol}`); } - const collateralIndex = collateralSymbols.indexOf(collSymbol); - const collateral = COLLATERALS[collateralIndex]; - const deposit = useInputFieldValue((value) => `${dn.format(value)} ${collateral.name}`); - const debt = useInputFieldValue((value) => `${dn.format(value)} BOLD`); + const collIndex = allCollContracts.findIndex(({ symbol }) => symbol === collSymbol); + if (!isCollIndex(collIndex)) { + throw new Error(`Unknown collateral symbol: ${collSymbol}`); + } + + const collaterals = allCollContracts.map(({ symbol }) => { + const collateral = KNOWN_COLLATERALS.find((c) => c.symbol === symbol); + if (!collateral) { + throw new Error(`Unknown collateral symbol: ${symbol}`); + } + return collateral; + }); + + const collateral = collaterals[collIndex]; + + const deposit = useInputFieldValue((value) => `${fmtnum(value)} ${collateral.name}`); + const debt = useInputFieldValue((value) => `${fmtnum(value)} BOLD`); const [interestRate, setInterestRate] = useState(dn.div(dn.from(INTEREST_RATE_DEFAULT, 18), 100)); const collPrice = usePrice(collateral.symbol); + const balances = Object.fromEntries(KNOWN_COLLATERAL_SYMBOLS.map((symbol) => ([ + symbol, + // known collaterals are static so we can safely call this hook in a .map() + useBalance(account.address, symbol), + ] as const))); + + const collBalance = balances[collateral.symbol]; + + const troveCount = useTroveCount(account.address, collIndex); + if (!collPrice) { return null; } @@ -99,17 +116,13 @@ export function BorrowScreen() { && interestRate && dn.gt(interestRate, 0); - const currentStepId = flow?.steps?.[currentStepIndex]?.id; - - const txMode = false; - return ( {content.borrowScreen.headline( - {COLLATERALS.map(({ symbol }) => ( + {allCollContracts.map(({ symbol }) => ( } > - {txMode && ( -
-
-
- next available trove: {match(availableTroveIndex) - .with({ status: "idle" }, () => "−") - .with({ status: "loading" }, () => "fetching") - .with({ status: "error" }, () => "error") - .with({ status: "success" }, ({ data }) => `#${data}`) - .exhaustive()} -
-
flow: {flow?.request.flowId}
-
- flow steps:{" "} - {flow?.steps && <>[{flow?.steps.map(({ id, txHash }) => txHash ? `${id} (ok)` : id).join(", ")}]} -
-
- current flow step: {currentStepIndex} ({flow?.steps && flow?.steps[currentStepIndex]?.id}) -
-
- flow step error:
{flow?.steps?.[currentStepIndex]?.error}
-
-
- {match([account, availableTroveIndex]) - .with([ - { status: "connected", address: P.nonNullable }, - { status: "success" }, - ], ([ - account, - availableTroveIndex, - ]) => ( - ( -
-
-
-
-
-
- ) - )) - .otherwise(() => null)} -
- )}
({ + items={collaterals.map(({ symbol, name }) => ({ icon: , label: name, - value: account.isConnected ? dn.format(ACCOUNT_BALANCES[symbol]) : "−", + value: account.isConnected + ? fmtnum(balances[symbol].data ?? 0) + : "−", }))} menuPlacement="end" menuWidth={300} onSelect={(index) => { deposit.setValue(""); + const { symbol } = collaterals[index]; router.push( - `/borrow/${COLLATERALS[index].symbol.toLowerCase()}`, + `/borrow/${symbol.toLowerCase()}`, { scroll: false }, ); }} - selected={collateralIndex} + selected={collIndex} /> } label={content.borrowScreen.depositField.label} @@ -285,15 +173,15 @@ export function BorrowScreen() { secondary={{ start: `$${ deposit.parsed - ? dn.format(dn.mul(collPrice, deposit.parsed), { digits: 2, trailingZeros: true }) + ? fmtnum(dn.mul(collPrice, deposit.parsed), "2z") : "0.00" }`, end: account.isConnected && ( { deposit.setValue( - dn.format(ACCOUNT_BALANCES[collateral.symbol]).replace(",", ""), + fmtnum(collBalance.data ?? 0).replace(",", ""), ); }} /> @@ -328,10 +216,7 @@ export function BorrowScreen() { secondary={{ start: `$${ debt.parsed - ? dn.format(dn.mul(collPrice, debt.parsed), { - digits: 2, - trailingZeros: true, - }) + ? fmtnum(dn.mul(collPrice, debt.parsed), "2z") : "0.00" }`, end: debtSuggestions && ( @@ -340,7 +225,7 @@ export function BorrowScreen() { s.debt && s.risk && ( { if (s.debt) { debt.setValue(dn.toString(s.debt, 0)); @@ -424,7 +309,25 @@ export function BorrowScreen() { size="large" wide onClick={() => { - router.push("/transactions/borrow"); + if (deposit.parsed && debt.parsed && account.address) { + txFlow.start({ + flowId: "openLoanPosition", + backLink: ["/borrow", "Back to editing"], + successLink: ["/", "Go to the Dashboard"], + successMessage: "The position has been created successfully.", + + collIndex, + owner: account.address, + ownerIndex: troveCount.data ?? 0, + collAmount: deposit.parsed, + boldAmount: debt.parsed, + upperHint: dnum18(0), + lowerHint: dnum18(0), + annualInterestRate: interestRate, + maxUpfrontFee: dnum18(maxUint256), + }); + router.push("/transactions"); + } }} />
diff --git a/frontend/app/src/screens/LeverageScreen/LeverageScreen.tsx b/frontend/app/src/screens/LeverageScreen/LeverageScreen.tsx index 1406f188..02b22af6 100644 --- a/frontend/app/src/screens/LeverageScreen/LeverageScreen.tsx +++ b/frontend/app/src/screens/LeverageScreen/LeverageScreen.tsx @@ -68,7 +68,8 @@ export function LeverageScreen() { && depositPreLeverage.parsed && dn.gt(depositPreLeverage.parsed, 0) && interestRate - && dn.gt(interestRate, 0); + && dn.gt(interestRate, 0) + && false; return ( )} - + ${fmtnum(loanDetails.liquidationPrice)} - {fmtnum(dn.mul(loan.interestRate, 100))}% + {fmtnum(loan.interestRate, 2, 100)}% - +
- {ltv && fmtnum(dn.mul(ltv, 100))}% + {fmtnum(ltv, "2z", 100)}%
@@ -442,48 +443,14 @@ function LoadingCard({ ); } -function Spinner({ - size = 24, -}: { - size?: number; -}) { - const spring = useSpring({ - from: { rotate: 0 }, - to: { rotate: 360 }, - loop: true, - config: { - duration: 1000, - }, - }); - return ( - `rotate(${r}deg)`), - }} - > - - - ); -} - function GridItem({ children, label, + title, }: { children: ReactNode; label: string; + title?: string; }) { return (
(null); + const loadingState = forcedLoadingState ?? match(loan) .returnType() .with({ status: "error" }, () => "error") @@ -60,11 +68,6 @@ export function LoanScreen() { .with({ data: P.nonNullable }, () => "success") .otherwise(() => "error"); - const setLoadingstate = (state: LoanLoadingState) => { - setForcedLoadingState(state); - }; - // const [loadingState, setLoadingstate] = useState("loading"); - const tabsTransition = useTransition(loadingState, { from: { opacity: 0 }, enter: { opacity: 1 }, @@ -78,36 +81,38 @@ export function LoanScreen() { return ( -
- loan state: {LOAN_STATES.map((s) => ( -
+ {LOAN_SCREEN_MANUAL_LOADING_STATE && ( +
+ loan state: {LOAN_STATES.map((s) => ( +
+ )} { - setLoadingstate("loading"); loan.refetch(); }} troveId={troveId} @@ -158,8 +162,12 @@ export function LoanScreen() { }))} selected={tab} onSelect={(index) => { + if (!loan.data) { + return; + } + const id = getPrefixedTroveId(loan.data.collIndex, loan.data.troveId); router.push( - `/loan/${TABS[index].id}?id=${loan.data?.troveId}`, + `/loan/${TABS[index].id}?id=${id}`, { scroll: false }, ); }} diff --git a/frontend/app/src/screens/LoanScreen/PanelClosePosition.tsx b/frontend/app/src/screens/LoanScreen/PanelClosePosition.tsx index a81bbc9e..9a1ea0cc 100644 --- a/frontend/app/src/screens/LoanScreen/PanelClosePosition.tsx +++ b/frontend/app/src/screens/LoanScreen/PanelClosePosition.tsx @@ -4,8 +4,10 @@ import { ConnectWarningBox } from "@/src/comps/ConnectWarningBox/ConnectWarningB import { Field } from "@/src/comps/Field/Field"; import { fmtnum } from "@/src/formatting"; import { getLoanDetails } from "@/src/liquity-math"; +import { getPrefixedTroveId } from "@/src/liquity-utils"; import { useAccount } from "@/src/services/Ethereum"; import { usePrice } from "@/src/services/Prices"; +import { useTransactionFlow } from "@/src/services/TransactionFlow"; import { css } from "@/styled-system/css"; import { Button, Dropdown, TokenIcon, TOKENS_BY_SYMBOL, VFlex } from "@liquity2/uikit"; import * as dn from "dnum"; @@ -15,6 +17,8 @@ import { useState } from "react"; export function PanelClosePosition({ loan }: { loan: PositionLoan }) { const router = useRouter(); const account = useAccount(); + const txFlow = useTransactionFlow(); + const collPrice = usePrice(loan.collateral); const boldPriceUsd = usePrice("BOLD"); const [tokenIndex, setTokenIndex] = useState(0); @@ -43,7 +47,7 @@ export function PanelClosePosition({ loan }: { loan: PositionLoan }) { ? loan.deposit : dn.sub(loan.deposit, amountToRepay); - const allowSubmit = account.isConnected; + const allowSubmit = account.isConnected && tokenIndex === 0; return ( <> @@ -189,7 +193,21 @@ export function PanelClosePosition({ loan }: { loan: PositionLoan }) { size="large" wide onClick={() => { - router.push("/transactions/close-loan"); + if (account.address) { + txFlow.start({ + flowId: "closeLoanPosition", + backLink: [ + `/loan/close?id=${loan.collIndex}:${loan.troveId}`, + "Back to editing", + ], + successLink: ["/", "Go to the dashboard"], + successMessage: "The loan position has been closed successfully.", + + collIndex: loan.collIndex, + prefixedTroveId: getPrefixedTroveId(loan.collIndex, loan.troveId), + }); + router.push("/transactions"); + } }} />
diff --git a/frontend/app/src/screens/LoanScreen/PanelUpdateBorrowPosition.tsx b/frontend/app/src/screens/LoanScreen/PanelUpdateBorrowPosition.tsx index bb649019..77317a31 100644 --- a/frontend/app/src/screens/LoanScreen/PanelUpdateBorrowPosition.tsx +++ b/frontend/app/src/screens/LoanScreen/PanelUpdateBorrowPosition.tsx @@ -9,12 +9,14 @@ import { InfoBox } from "@/src/comps/InfoBox/InfoBox"; import { InputTokenBadge } from "@/src/comps/InputTokenBadge/InputTokenBadge"; import { ValueUpdate } from "@/src/comps/ValueUpdate/ValueUpdate"; import { ETH_MAX_RESERVE } from "@/src/constants"; -import { ACCOUNT_BALANCES } from "@/src/demo-mode"; +import { dnum18, dnumMin } from "@/src/dnum-utils"; import { useInputFieldValue } from "@/src/form-utils"; import { fmtnum, formatRisk } from "@/src/formatting"; import { getLoanDetails } from "@/src/liquity-math"; -import { useAccount } from "@/src/services/Ethereum"; +import { getPrefixedTroveId } from "@/src/liquity-utils"; +import { useAccount, useBalance } from "@/src/services/Ethereum"; import { usePrice } from "@/src/services/Prices"; +import { useTransactionFlow } from "@/src/services/TransactionFlow"; import { riskLevelToStatusMode } from "@/src/uikit-utils"; import { css } from "@/styled-system/css"; import { @@ -29,6 +31,7 @@ import { TOKENS_BY_SYMBOL, VFlex, } from "@liquity2/uikit"; +import { maxUint256 } from "viem"; import * as dn from "dnum"; import { useRouter } from "next/navigation"; @@ -36,13 +39,18 @@ import { useState } from "react"; type ValueUpdateMode = "add" | "remove"; -export function PanelUpdateBorrowPosition({ loan }: { loan: PositionLoan }) { +export function PanelUpdateBorrowPosition({ + loan, +}: { + loan: PositionLoan; +}) { const router = useRouter(); const account = useAccount(); + const txFlow = useTransactionFlow(); const collateral = TOKENS_BY_SYMBOL[loan.collateral]; const collPrice = usePrice(collateral.symbol); - const boldPriceUsd = usePrice("BOLD") ?? dn.from(0, 18); + const boldPriceUsd = usePrice("BOLD") ?? dnum18(0); // deposit change const [depositMode, setDepositMode] = useState("add"); @@ -55,11 +63,6 @@ export function PanelUpdateBorrowPosition({ loan }: { loan: PositionLoan }) { : dn.add(loan.deposit, depositChange.parsed) ); - const collMax = depositMode === "remove" ? loan.deposit : dn.sub( - ACCOUNT_BALANCES[collateral.symbol], - ETH_MAX_RESERVE, - ); - // debt change const [debtMode, setDebtMode] = useState("add"); const debtChange = useInputFieldValue((value) => dn.format(value)); @@ -71,7 +74,21 @@ export function PanelUpdateBorrowPosition({ loan }: { loan: PositionLoan }) { : dn.add(loan.borrowed, debtChange.parsed) ); - const boldMax = debtMode === "remove" ? ACCOUNT_BALANCES["BOLD"] : null; + const collBalance = useBalance(account.address, collateral.symbol); + const boldBalance = useBalance(account.address, "BOLD"); + + const collMax = depositMode === "remove" ? loan.deposit : ( + collBalance.data + ? dn.sub(collBalance.data, ETH_MAX_RESERVE) + : dnum18(0) + ); + + const boldMax = debtMode === "remove" && boldBalance.data + ? dnumMin( + boldBalance.data, + loan.borrowed, + ) + : null; const loanDetails = getLoanDetails( loan.deposit, @@ -90,8 +107,8 @@ export function PanelUpdateBorrowPosition({ loan }: { loan: PositionLoan }) { ); const allowSubmit = account.isConnected && ( - !dn.eq(loanDetails.deposit ?? dn.from(0, 18), newLoanDetails.deposit ?? dn.from(0, 18)) - || !dn.eq(loanDetails.debt ?? dn.from(0, 18), newLoanDetails.debt ?? dn.from(0, 18)) + !dn.eq(loanDetails.deposit ?? dnum18(0), newLoanDetails.deposit ?? dnum18(0)) + || !dn.eq(loanDetails.debt ?? dnum18(0), newLoanDetails.debt ?? dnum18(0)) ); return ( @@ -119,9 +136,13 @@ export function PanelUpdateBorrowPosition({ loan }: { loan: PositionLoan }) { { label: "Deposit", panelId: "panel-deposit", tabId: "tab-deposit" }, { label: "Withdraw", panelId: "panel-withdraw", tabId: "tab-withdraw" }, ]} - onSelect={(index) => { + onSelect={(index, { origin, event }) => { setDepositMode(index === 1 ? "remove" : "add"); - depositChange.setValue("0"); + depositChange.setValue(""); + if (origin !== "keyboard") { + event.preventDefault(); + depositChange.focus(); + } }} selected={depositMode === "remove" ? 1 : 0} /> @@ -189,9 +210,13 @@ export function PanelUpdateBorrowPosition({ loan }: { loan: PositionLoan }) { { label: "Borrow", panelId: "panel-borrow", tabId: "tab-borrow" }, { label: "Repay", panelId: "panel-repay", tabId: "tab-repay" }, ]} - onSelect={(index) => { + onSelect={(index, { origin, event }) => { setDebtMode(index === 1 ? "remove" : "add"); - debtChange.setValue("0"); + debtChange.setValue(""); + if (origin !== "keyboard") { + event.preventDefault(); + debtChange.focus(); + } }} selected={debtMode === "remove" ? 1 : 0} /> @@ -348,7 +373,22 @@ export function PanelUpdateBorrowPosition({ loan }: { loan: PositionLoan }) { size="large" wide onClick={() => { - router.push("/transactions/update-loan"); + if (account.address) { + txFlow.start({ + flowId: "updateLoanPosition", + backLink: [`/loan?id=${loan.collIndex}:${loan.troveId}`, "Back to editing"], + successLink: ["/", "Go to the dashboard"], + successMessage: "The position has been updated successfully.", + + collIndex: loan.collIndex, + prefixedTroveId: getPrefixedTroveId(loan.collIndex, loan.troveId), + owner: account.address, + collChange: dn.sub(newDeposit ?? dnum18(0), loan.deposit), + boldChange: dn.sub(newDebt ?? dnum18(0), loan.borrowed), + maxUpfrontFee: dnum18(maxUint256), + }); + router.push("/transactions"); + } }} />
diff --git a/frontend/app/src/screens/LoanScreen/PanelUpdateLeveragePosition.tsx b/frontend/app/src/screens/LoanScreen/PanelUpdateLeveragePosition.tsx index ce66bc3f..60c87aaf 100644 --- a/frontend/app/src/screens/LoanScreen/PanelUpdateLeveragePosition.tsx +++ b/frontend/app/src/screens/LoanScreen/PanelUpdateLeveragePosition.tsx @@ -121,21 +121,19 @@ export function PanelUpdateLeveragePosition({ loan }: { loan: PositionLoan }) { setAgreeToLiquidationRisk(false); }, [newLoanDetails.status]); - const allowSubmit = ( - account.isConnected - ) && ( - newLoanDetails.status !== "at-risk" || agreeToLiquidationRisk - ) && ( - newLoanDetails.status !== "underwater" && newLoanDetails.status !== "liquidatable" - ) && ( - // either the deposit or the leverage factor has changed - !dn.eq( - initialLoanDetails.deposit ?? dn.from(0, 18), - newLoanDetails.deposit ?? dn.from(0, 18), - ) || ( - initialLoanDetails.leverageFactor !== newLoanDetails.leverageFactor - ) - ); + const allowSubmit = account.isConnected + && newLoanDetails.status !== "at-risk" || agreeToLiquidationRisk + && newLoanDetails.status !== "underwater" && newLoanDetails.status !== "liquidatable" + && ( + // either the deposit or the leverage factor has changed + !dn.eq( + initialLoanDetails.deposit ?? dn.from(0, 18), + newLoanDetails.deposit ?? dn.from(0, 18), + ) || ( + initialLoanDetails.leverageFactor !== newLoanDetails.leverageFactor + ) + ) + && false; return ( <> diff --git a/frontend/app/src/screens/LoanScreen/PanelUpdateRate.tsx b/frontend/app/src/screens/LoanScreen/PanelUpdateRate.tsx index 6b324e22..4e6872b1 100644 --- a/frontend/app/src/screens/LoanScreen/PanelUpdateRate.tsx +++ b/frontend/app/src/screens/LoanScreen/PanelUpdateRate.tsx @@ -5,21 +5,26 @@ import { Field } from "@/src/comps/Field/Field"; import { InfoBox } from "@/src/comps/InfoBox/InfoBox"; import { InterestRateField } from "@/src/comps/InterestRateField/InterestRateField"; import { ValueUpdate } from "@/src/comps/ValueUpdate/ValueUpdate"; +import { dnum18 } from "@/src/dnum-utils"; import { useInputFieldValue } from "@/src/form-utils"; import { fmtnum, formatRisk } from "@/src/formatting"; import { getLoanDetails } from "@/src/liquity-math"; +import { getPrefixedTroveId } from "@/src/liquity-utils"; import { useAccount } from "@/src/services/Ethereum"; import { usePrice } from "@/src/services/Prices"; +import { useTransactionFlow } from "@/src/services/TransactionFlow"; import { riskLevelToStatusMode } from "@/src/uikit-utils"; import { css } from "@/styled-system/css"; import { Button, HFlex, InfoTooltip, StatusDot, TOKENS_BY_SYMBOL } from "@liquity2/uikit"; import * as dn from "dnum"; import { useRouter } from "next/navigation"; import { useState } from "react"; +import { maxUint256 } from "viem"; export function PanelUpdateRate({ loan }: { loan: PositionLoan }) { const router = useRouter(); const account = useAccount(); + const txFlow = useTransactionFlow(); const collateral = TOKENS_BY_SYMBOL[loan.collateral]; const collPrice = usePrice(collateral.symbol); @@ -145,7 +150,26 @@ export function PanelUpdateRate({ loan }: { loan: PositionLoan }) { size="large" wide onClick={() => { - router.push("/transactions/update-loan"); + if (account.address) { + txFlow.start({ + flowId: "updateLoanInterestRate", + backLink: [ + `/loan/rate?id=${loan.collIndex}:${loan.troveId}`, + "Back to editing", + ], + successLink: ["/", "Go to the dashboard"], + successMessage: "The position interest rate has been updated successfully.", + + collIndex: loan.collIndex, + interestRate, + lowerHint: dnum18(0), + maxUpfrontFee: dnum18(maxUint256), + owner: account.address, + prefixedTroveId: getPrefixedTroveId(loan.collIndex, loan.troveId), + upperHint: dnum18(0), + }); + router.push("/transactions"); + } }} />
diff --git a/frontend/app/src/screens/TransactionsScreen/LoanCard.tsx b/frontend/app/src/screens/TransactionsScreen/LoanCard.tsx new file mode 100644 index 00000000..dab9fce2 --- /dev/null +++ b/frontend/app/src/screens/TransactionsScreen/LoanCard.tsx @@ -0,0 +1,675 @@ +import type { PositionLoan } from "@/src/types"; +import type { ReactNode } from "react"; +import type { LoadingState } from "./TransactionsScreen"; + +import { INFINITY } from "@/src/characters"; +import { Spinner } from "@/src/comps/Spinner/Spinner"; +import { Value } from "@/src/comps/Value/Value"; +import { formatRisk } from "@/src/formatting"; +import { fmtnum } from "@/src/formatting"; +import { getLoanDetails } from "@/src/liquity-math"; +import { usePrice } from "@/src/services/Prices"; +import { riskLevelToStatusMode } from "@/src/uikit-utils"; +import { roundToDecimal } from "@/src/utils"; +import { css } from "@/styled-system/css"; +import { token } from "@/styled-system/tokens"; +import { Button, HFlex, IconBorrow, IconLeverage, StatusDot, TokenIcon, TOKENS_BY_SYMBOL } from "@liquity2/uikit"; +import { a, useSpring } from "@react-spring/web"; +import * as dn from "dnum"; +import { match, P } from "ts-pattern"; + +const LOAN_CARD_HEIGHT = 246 - 16; +const LOAN_CARD_HEIGHT_REDUCED = 176; + +export function LoanCard({ + leverageMode, + loadingState, + loan, + prevLoan, + onRetry, +}: { + leverageMode: boolean; + loadingState: LoadingState; + loan: PositionLoan | null; + prevLoan?: PositionLoan | null; + onRetry: () => void; +}) { + const collateral = ( + loan && TOKENS_BY_SYMBOL[loan.collateral] + ) || ( + prevLoan && TOKENS_BY_SYMBOL[prevLoan.collateral] + ); + const collPriceUsd = usePrice(collateral ? collateral.symbol : null); + + const isLoanClosing = prevLoan && !loan; + + const loanDetails = loan && collateral && getLoanDetails( + loan.deposit, + loan.borrowed, + loan.interestRate, + collateral.collateralRatio, + collPriceUsd, + ); + + const prevLoanDetails = prevLoan && collateral && getLoanDetails( + prevLoan.deposit, + prevLoan.borrowed, + prevLoan.interestRate, + collateral.collateralRatio, + collPriceUsd, + ); + + const { + ltv, + depositPreLeverage, + leverageFactor, + redemptionRisk, + liquidationRisk, + } = loanDetails || {}; + + const maxLtv = collateral && dn.div( + dn.from(1, 18), + collateral.collateralRatio, + ); + + return ( + + {isLoanClosing + ? ( + <> + +
+ {collateral && ( + +
+
+ {fmtnum(0)} {collateral.name} +
+ {prevLoan && ( +
+ {fmtnum(prevLoan.deposit)} {collateral.name} +
+ )} +
+
+ )} +
+ + ) + : loan + && loanDetails + && collateral + && typeof leverageFactor === "number" + && depositPreLeverage + && maxLtv + && liquidationRisk + && ( + <> + {leverageMode + ? ( + + ) + : ( + + )} +
+ {leverageMode + ? ( + + + {fmtnum(depositPreLeverage)} {collateral.name} + + + ) + : ( + +
+
+ {fmtnum(loan.deposit)} {collateral.name} +
+ {prevLoan && !dn.eq(prevLoan.deposit, loan.deposit) && ( +
+ {fmtnum(prevLoan.deposit)} {collateral.name} +
+ )} +
+
+ )} + +
+ + ${fmtnum(loanDetails.liquidationPrice)} + + {loanDetails?.liquidationPrice + && prevLoanDetails?.liquidationPrice + && !dn.eq( + prevLoanDetails.liquidationPrice, + loanDetails.liquidationPrice, + ) + && ( +
+ ${fmtnum(prevLoanDetails.liquidationPrice)} +
+ )} +
+
+ +
+ {fmtnum(dn.mul(loan.interestRate, 100))}% + {prevLoan && !dn.eq(prevLoan.interestRate, loan.interestRate) && ( +
+ {fmtnum(dn.mul(prevLoan.interestRate, 100))}% +
+ )} +
+
+ +
+
+ {ltv && fmtnum(dn.mul(ltv, 100))}% +
+ {ltv + && prevLoanDetails?.ltv + && !dn.eq(prevLoanDetails.ltv, ltv) + && ( +
+ {prevLoanDetails.ltv && fmtnum(dn.mul(prevLoanDetails.ltv, 100))}% +
+ )} +
+
+ + + + {formatRisk(liquidationRisk)} + {prevLoanDetails && liquidationRisk !== prevLoanDetails.liquidationRisk && ( + <> + +
+ {formatRisk(prevLoanDetails.liquidationRisk)} +
+ + )} +
+
+ {redemptionRisk && ( + + + + {formatRisk(redemptionRisk)} + {prevLoanDetails && redemptionRisk !== prevLoanDetails.redemptionRisk && ( + <> + +
+ {formatRisk(prevLoanDetails.redemptionRisk)} +
+ + )} +
+
+ )} +
+ + )} +
+ ); +} + +function TotalDebt({ + positive, + loan, + prevLoan, +}: { + positive?: boolean; + loan: PositionLoan; + prevLoan?: PositionLoan | null; +}) { + return ( +
+
+
+
+ {fmtnum(loan.borrowed)} +
+ + {prevLoan && !dn.eq(prevLoan.borrowed, loan.borrowed) && ( +
+ {fmtnum(prevLoan.borrowed)} +
+ )} +
+
+
+ ); +} + +function TotalExposure({ + loan, + loanDetails, +}: { + loan: PositionLoan; + loanDetails: ReturnType; +}) { + const collateral = loan && TOKENS_BY_SYMBOL[loan.collateral]; + return ( +
+
+
+
{fmtnum(loan.deposit)}
+ +
+
+ + {loanDetails.status === "underwater" || loanDetails.leverageFactor === null + ? INFINITY + : `${roundToDecimal(loanDetails.leverageFactor, 1)}x`} + +
+
+
+
+
+ ); +} + +function LoadingCard({ + children, + height, + leverage, + loadingState, + onRetry, +}: { + children: ReactNode; + height: number; + leverage: boolean; + loadingState: LoadingState; + onRetry: () => void; +}) { + const title = leverage ? "Leverage loan" : "BOLD loan"; + + const spring = useSpring({ + to: match(loadingState) + .with( + P.union( + "loading", + "error", + "not-found", + ), + (s) => ({ + cardtransform: "scale3d(0.95, 0.95, 1)", + containerHeight: ( + window.innerHeight + - 120 // top bar + - 24 * 2 // padding + - 48 // bottom bar 1 + - 40 + // - 40 // bottom bar 2 + ), + cardHeight: s === "error" || s === "not-found" ? 180 : 120, + cardBackground: token("colors.blue:50"), + cardColor: token("colors.blue:950"), + }), + ) + .otherwise(() => ({ + cardtransform: "scale3d(1, 1, 1)", + containerHeight: height, + cardHeight: height, + cardBackground: token("colors.blue:950"), + cardColor: token("colors.white"), + })), + config: { + mass: 1, + tension: 2000, + friction: 120, + }, + }); + + return ( + + +

+
+
+ {leverage + ? + : } +
+ {title} +
+

+ {match(loadingState) + .with("loading", () => ( +
+ Fetching + +
+ )) + .with("error", () => ( +
+
Error fetching data
+
+ )) + .otherwise(() => ( +
+ {children} +
+ ))} +
+
+ ); +} + +function GridItem({ + children, + label, + title, +}: { + children: ReactNode; + label: string; + title?: string; +}) { + return ( +
+
+ {label} +
+
+ {children} +
+
+ ); +} diff --git a/frontend/app/src/screens/TransactionsScreen/TransactionsScreen.tsx b/frontend/app/src/screens/TransactionsScreen/TransactionsScreen.tsx new file mode 100644 index 00000000..e2a7c2c3 --- /dev/null +++ b/frontend/app/src/screens/TransactionsScreen/TransactionsScreen.tsx @@ -0,0 +1,375 @@ +"use client"; + +import type { FlowStepStatus } from "@/src/services/TransactionFlow"; +import type { ReactNode } from "react"; + +import { Screen } from "@/src/comps/Screen/Screen"; +import { Spinner } from "@/src/comps/Spinner/Spinner"; +import { useTransactionFlow } from "@/src/services/TransactionFlow"; +import { css } from "@/styled-system/css"; +import { AnchorButton, AnchorTextButton, Button, HFlex, IconCross, VFlex } from "@liquity2/uikit"; +import { a, useTransition } from "@react-spring/web"; +import Link from "next/link"; +import { match, P } from "ts-pattern"; + +export type LoadingState = + | "error" + | "loading" + | "not-found" + | "success"; + +export function TransactionsScreen() { + const { + currentStepIndex, + flow, + flowDeclaration: fd, + signAndSend, + } = useTransactionFlow(); + + if (!flow?.steps || !fd) { + return ; + } + + const currentStep = flow.steps[currentStepIndex]; + + return ( + + + + + + + + + {currentStep.error && ( +
+
{currentStep.error}
+
+ )} + + {currentStep.txStatus === "confirmed" && ( +
+ {flow.request.successMessage} +
+ )} + +
+ {currentStep.txStatus === "confirmed" + ? ( + + + + ) + : ( +
+ {currentStepIndex > -1 && ( +
+ {flow.steps.map((step, index) => ( + + ))} +
+ )} + {currentStepIndex === 0 + && currentStep.txStatus !== "awaiting-confirmation" + && currentStep.txStatus !== "confirmed" && flow.request.backLink && ( +
+ + + +
+ )} +
+
+ ); +} + +export function TransactionDetailsRow({ + label, + value, + valueSize = "normal", + secondarySize = "normal", +}: { + label: ReactNode; + value: ReactNode; + valueSize?: "normal" | "small"; + secondarySize?: "normal" | "large"; +}) { + return ( + + {Array.isArray(label) + ? ( + + + {label[0]} + + {label.slice(1).map((v, index) => ( +
+ {v} +
+ ))} +
+ ) + : {label}} + {Array.isArray(value) + ? ( + + + {value[0]} + + {value.slice(1).map((v, index) => ( +
+ {v} +
+ ))} +
+ ) + : ( + + {value} + + )} +
+ ); +} + +function NoTransactionsScreen() { + return ( +
+
+ No ongoing transactions. +
+
+ + + +
+
+ ); +} + +function FlowStep({ + isCurrent, + label, + status, +}: { + isCurrent: boolean; + label: string; + status: FlowStepStatus; +}) { + const iconTransition = useTransition(status, { + from: { + opacity: 0, + width: 0, + transform: "scale(0)", + }, + enter: { + opacity: 1, + width: 16 + 8, + transform: "scale(1)", + }, + leave: { + opacity: 0, + width: 0, + transform: "scale(0)", + immediate: true, + }, + config: { + mass: 2, + tension: 1200, + friction: 80, + }, + }); + + return ( +
+
{label}
+ {iconTransition((style, status) => + match(status) + .with( + P.union( + "awaiting-signature", + "awaiting-confirmation", + "confirmed", + "error", + ), + (status) => ( + + "var(--color-error)") + .with("confirmed", () => "var(--color-success)") + .otherwise(() => undefined), + }} + > + {match(status) + .with("error", () => ) + .with("confirmed", () => ) + .otherwise(() => )} + + + ), + ) + .otherwise(() => null) + )} +
+ ); +} + +function Tick() { + return ( + + + + ); +} diff --git a/frontend/app/src/services/Ethereum.tsx b/frontend/app/src/services/Ethereum.tsx index 226ae789..5a85a17f 100644 --- a/frontend/app/src/services/Ethereum.tsx +++ b/frontend/app/src/services/Ethereum.tsx @@ -2,11 +2,15 @@ import "@rainbow-me/rainbowkit/styles.css"; +import type { Token } from "@/src/types"; import type { Address } from "@liquity2/uikit"; import type { ComponentProps, ReactNode } from "react"; import type { Chain } from "wagmi/chains"; +import { useContracts } from "@/src/contracts"; +import { ACCOUNT_BALANCES } from "@/src/demo-mode"; import { useDemoMode } from "@/src/demo-mode"; +import { dnum18 } from "@/src/dnum-utils"; import { CHAIN_BLOCK_EXPLORER, CHAIN_CONTRACT_ENS_REGISTRY, @@ -16,10 +20,13 @@ import { CHAIN_ID, CHAIN_NAME, CHAIN_RPC_URL, + CONTRACT_BOLD_TOKEN, + LQTY_TOKEN, + LUSD_TOKEN, WALLET_CONNECT_PROJECT_ID, } from "@/src/env"; import { noop } from "@/src/utils"; -import { useTheme } from "@liquity2/uikit"; +import { isCollateralSymbol, useTheme } from "@liquity2/uikit"; import { getDefaultConfig, lightTheme, @@ -29,7 +36,16 @@ import { } from "@rainbow-me/rainbowkit"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { useMemo } from "react"; -import { http, useAccount as useAccountWagmi, useEnsName, WagmiProvider } from "wagmi"; +import { match } from "ts-pattern"; +import { erc20Abi } from "viem"; +import { + http, + useAccount as useAccountWagmi, + useBalance as useBalanceWagmi, + useEnsName, + useReadContract, + WagmiProvider, +} from "wagmi"; const queryClient = new QueryClient(); @@ -62,12 +78,59 @@ export function useAccount(): const ensName = useEnsName({ address: account?.address }); return demoMode.enabled ? demoMode.account : { ...account, - connect: account.isConnected && openConnectModal || noop, + connect: openConnectModal || noop, disconnect: account.isConnected && openAccountModal || noop, ensName: ensName.data ?? undefined, }; } +export function useBalance( + address: Address | undefined, + token: Token["symbol"] | undefined, +) { + const demoMode = useDemoMode(); + const contracts = useContracts(); + + const tokenAddress = match(token) + .when( + (symbol) => Boolean(symbol && isCollateralSymbol(symbol) && symbol !== "ETH"), + (symbol) => { + if (!symbol || !isCollateralSymbol(symbol) || symbol === "ETH") { + return null; + } + const collateral = contracts.collaterals.find((c) => c.symbol === symbol); + return collateral?.contracts.Token.address ?? null; + }, + ) + .with("BOLD", () => CONTRACT_BOLD_TOKEN) + .with("LQTY", () => LQTY_TOKEN) + .with("LUSD", () => LUSD_TOKEN) + .otherwise(() => null); + + const tokenBalance = useReadContract({ + address: tokenAddress ?? undefined, + abi: erc20Abi, + functionName: "balanceOf", + args: address && [address], + query: { + select: (value) => dnum18(value ?? 0n), + enabled: Boolean(!demoMode.enabled && address && token !== "ETH"), + }, + }); + + const ethBalance = useBalanceWagmi({ + address, + query: { + select: ({ value }) => dnum18(value ?? 0n), + enabled: Boolean(!demoMode.enabled && address && token === "ETH"), + }, + }); + + return demoMode.enabled && token + ? { data: ACCOUNT_BALANCES[token], isLoading: false } + : (token === "ETH" ? ethBalance : tokenBalance); +} + function useRainbowKitProps(): Omit, "children"> { const theme = useTheme(); return { diff --git a/frontend/app/src/services/Prices.tsx b/frontend/app/src/services/Prices.tsx index 9288901c..468a5686 100644 --- a/frontend/app/src/services/Prices.tsx +++ b/frontend/app/src/services/Prices.tsx @@ -15,7 +15,6 @@ import { RETH_PRICE as DEMO_RETH_PRICE, STETH_PRICE as DEMO_STETH_PRICE, } from "@/src/demo-mode"; -import { DEMO_MODE } from "@/src/env"; import * as dn from "dnum"; import { createContext, useContext, useEffect, useState } from "react"; import { useReadContract } from "wagmi"; diff --git a/frontend/app/src/services/TransactionFlow.tsx b/frontend/app/src/services/TransactionFlow.tsx index 183e5115..f8f69afb 100644 --- a/frontend/app/src/services/TransactionFlow.tsx +++ b/frontend/app/src/services/TransactionFlow.tsx @@ -4,80 +4,127 @@ // executed in sequence. It only stores the last series of transactions. // // Naming conventions: +// - Request: The initial request parameters that starts a flow. // - Flow: A series of transactions that are executed in sequence. -// - Flow steps: Series of transactions in a flow. -// - Request: The initial request that starts a flow. -// - Flow declaration: Contains the logic for a specific flow. -// - Flow state: The state of a transaction flow, as stored in local storage (steps + request). - -import type { Request as OpenLoanPositionRequest } from "@/src/tx-flows/openLoanPosition.ts"; -import type { Request as RepayAndCloseLoanPositionRequest } from "@/src/tx-flows/repayAndCloseLoanPosition.ts"; -import type { Request as UpdateLoanPositionRequest } from "@/src/tx-flows/updateLoanPosition.ts"; +// - Flow steps: Series of transactions in a flow (determined by the request). +// - Flow declaration: Contains the logic for a specific flow (get steps, parse request, tx params). +// - Flow context: a transaction flow as stored in local storage (steps + request). + +import type { Request as CloseLoanPositionRequest } from "@/src/tx-flows/closeLoanPosition"; +import type { Request as OpenLoanPositionRequest } from "@/src/tx-flows/openLoanPosition"; +import type { Request as UpdateLoanInterestRateRequest } from "@/src/tx-flows/updateLoanInterestRate"; +import type { Request as UpdateLoanPositionRequest } from "@/src/tx-flows/updateLoanPosition"; import type { Address } from "@/src/types"; -import type { ReactNode } from "react"; +import type { WriteContractParameters } from "@wagmi/core"; +import type { ComponentType, ReactNode } from "react"; import { LOCAL_STORAGE_PREFIX } from "@/src/constants"; import { useContracts } from "@/src/contracts"; import { jsonParseWithDnum, jsonStringifyWithDnum } from "@/src/dnum-utils"; import { useAccount, useWagmiConfig } from "@/src/services/Ethereum"; -import { openLoanPosition } from "@/src/tx-flows/openLoanPosition.ts"; -import { repayAndCloseLoanPosition } from "@/src/tx-flows/repayAndCloseLoanPosition.ts"; -import { updateLoanPosition } from "@/src/tx-flows/updateLoanPosition.ts"; +import { closeLoanPosition } from "@/src/tx-flows/closeLoanPosition"; +import { openLoanPosition } from "@/src/tx-flows/openLoanPosition"; +import { updateLoanInterestRate } from "@/src/tx-flows/updateLoanInterestRate"; +import { updateLoanPosition } from "@/src/tx-flows/updateLoanPosition"; import { noop } from "@/src/utils"; import { vAddress } from "@/src/valibot-utils"; import { useQuery } from "@tanstack/react-query"; import { createContext, useCallback, useContext, useEffect, useState } from "react"; import * as v from "valibot"; -import { useWaitForTransactionReceipt, useWriteContract } from "wagmi"; +import { useTransactionReceipt, useWriteContract } from "wagmi"; const TRANSACTION_FLOW_KEY = `${LOCAL_STORAGE_PREFIX}transaction_flow`; export type FlowRequest = | OpenLoanPositionRequest - | RepayAndCloseLoanPositionRequest - | UpdateLoanPositionRequest; - -const flowDeclarations: FlowDeclarations = { + | UpdateLoanPositionRequest + | UpdateLoanInterestRateRequest + | CloseLoanPositionRequest; + +const flowDeclarations: { + [K in FlowIdFromFlowRequest]: FlowDeclaration< + Extract, + any // Use 'any' here to allow any StepId type + >; +} = { + closeLoanPosition, openLoanPosition, - repayAndCloseLoanPosition, + updateLoanInterestRate, updateLoanPosition, }; const FlowIdSchema = v.union([ + v.literal("closeLoanPosition"), v.literal("openLoanPosition"), - v.literal("repayAndCloseLoanPosition"), v.literal("updateLoanPosition"), + v.literal("updateLoanInterestRate"), ]); +type ExtractStepId = T extends FlowDeclaration ? S : never; + type FlowDeclarations = { - [K in FlowId]: FlowDeclaration>; + [K in FlowIdFromFlowRequest]: FlowDeclaration< + Extract, + ExtractStepId + >; }; -function getFlowDeclaration>( - flowId: T, -): FlowDeclaration> { +export type FlowId = keyof FlowDeclarations; + +function getFlowDeclaration< + T extends FlowIdFromFlowRequest, +>(flowId: T): FlowDeclaration< + Extract, + ExtractStepId +> { return flowDeclarations[flowId]; } -type FlowId = FR["flowId"]; - -export type FlowSteps = Array<{ - id: string; - error: string | null; - txHash: string | null; -}>; +export type FlowIdFromFlowRequest = FR["flowId"]; +export type FlowRequestFromFlowId = Extract; +export type FlowContextFromFlowId = FlowContext>; export const FlowStepsSchema = v.union([ v.null(), - v.array(v.object({ - id: v.string(), - error: v.union([v.null(), v.string()]), - txHash: v.union([v.null(), v.string()]), - })), + v.array( + v.union([ + v.object({ + id: v.string(), + error: v.string(), + txHash: v.union([v.null(), v.string()]), + txStatus: v.literal("error"), + }), + v.object({ + id: v.string(), + error: v.null(), + txHash: v.union([v.null(), v.string()]), + txStatus: v.union([ + v.literal("idle"), + v.literal("awaiting-signature"), + v.literal("awaiting-confirmation"), + v.literal("confirmed"), + ]), + }), + ]), + ), ]); -// The state of a transaction flow, as stored in local storage -export type FlowState = { +type FlowStepUpdate = + | { error: string; txHash: null | string; txStatus: "error" } + | { + error: null; + txHash: null | string; + txStatus: "idle" | "awaiting-signature" | "awaiting-confirmation" | "confirmed"; + }; + +export type FlowSteps = NonNullable< + v.InferOutput +>; + +export type FlowStepStatus = FlowSteps[number]["txStatus"]; + +// The context of a transaction flow, as stored in local storage +export type FlowContext = { account: Address | null; request: FR; steps: FlowSteps | null; @@ -87,27 +134,46 @@ const FlowStateSchema = v.object({ account: vAddress(), request: v.looseObject({ flowId: FlowIdSchema, + backLink: v.union([ + v.null(), + v.tuple([ + v.string(), // path + v.string(), // label + ]), + ]), + successLink: v.tuple([ + v.string(), // path + v.string(), // label + ]), }), steps: FlowStepsSchema, }); -type GetStepsFn = (args: { +type GetStepsFn = (args: { account: ReturnType; contracts: ReturnType; request: FR; wagmiConfig: ReturnType; -}) => Promise; +}) => Promise; -type WriteContractParamsFn = (args: { +type WriteContractParamsFn = (args: { contracts: ReturnType; request: FR; - stepId: string; -}) => Promise["writeContract"]>[0] | null>; - -export type FlowDeclaration = { - getSteps: GetStepsFn; + stepId: StepId; +}) => Promise; + +export type FlowDeclaration< + FR extends FlowRequest, + StepId extends string = string, +> = { + title: ReactNode; + subtitle: ReactNode; + Summary: ComponentType<{ flow: FlowContext }>; + Details: ComponentType<{ flow: FlowContext }>; + getSteps: GetStepsFn; + getStepName: (stepId: StepId) => string; parseRequest: (request: unknown) => FR | null; - writeContractParams: WriteContractParamsFn; + writeContractParams: WriteContractParamsFn; }; type Context = { @@ -115,7 +181,8 @@ type Context = { discard: () => void; signAndSend: () => Promise; start: (request: FR) => void; - flow: FlowState | null; + flow: null | FlowContext; + flowDeclaration: null | FlowDeclaration>; }; const TransactionFlowContext = createContext({ @@ -124,156 +191,154 @@ const TransactionFlowContext = createContext({ signAndSend: async () => {}, start: noop, flow: null, + flowDeclaration: null, }); -type ComponentState = { - flow: null | FlowState; - flowStatus: - | null // no flow - | "awaiting-steps" // waiting for steps to be fetched (when start() gets called) - | "ready"; // flow loaded and ready to be executed -}; - export function TransactionFlow({ children }: { children: ReactNode }) { const wagmiConfig = useWagmiConfig(); const account = useAccount(); const contracts = useContracts(); - const [{ - flow, - flowStatus, - }, setState] = useState(() => { - const flow = flowStateStorage.get() ?? null; - const flowStatus = flow ? "ready" : null; - return { flow, flowStatus }; + const [{ flow }, setFlowAndStatus] = useState<{ + flow: null | FlowContext; + }>({ + flow: null, }); - const currentStepIndex = flow?.steps && flow?.steps.at(-1)?.txHash - ? flow?.steps.length - 1 - : (flow?.steps?.findIndex((step) => !step.txHash) ?? -1); + const currentStepIndex = getCurrentStepIndex(flow); - // initiate a new transaction flow + // initiate a new transaction flow (triggers fetching the steps) const start: Context["start"] = useCallback((request) => { - if (account.address) { - setState({ - flow: { - account: account.address, - request, - steps: null, - }, - flowStatus: "awaiting-steps", - }); + if (!account.address) { + return; } + + const newFlow = { + account: account.address, + request, + steps: null, + }; + + setFlowAndStatus({ flow: newFlow }); + FlowContextStorage.set(newFlow); }, [account]); // discard the current transaction flow (remove it from local storage) const discard: Context["discard"] = useCallback(() => { - flowStateStorage.clear(); - setState({ flow: null, flowStatus: null }); + setFlowAndStatus({ flow: null }); + FlowContextStorage.clear(); }, []); - const stepsQuery = useQuery({ + // update a specific step in the flow + const updateStep = (index: number, update: FlowStepUpdate) => { + if (!flow) { + return; + } + + const newFlow = { + ...flow, + steps: flow.steps?.map((step, index_) => ( + index_ === index ? { ...step, ...update } : step + )) ?? null, + }; + + // update state + local storage + setFlowAndStatus({ flow: newFlow }); + FlowContextStorage.set(newFlow); + }; + + useSteps({ + flow, enabled: Boolean( flow && account.address && flow.account === account.address - && flowStatus === "awaiting-steps", + && flow.steps === null, ), - queryKey: [ - "transaction-flow-steps", - jsonStringifyWithDnum(flow?.request), - account.address, - ], - queryFn: async () => { - if (!flow || !account.address || flow.account !== account.address) { + account, + contracts, + wagmiConfig, + onSteps: (steps) => { + if (!flow) { return; } - return getFlowDeclaration(flow.request.flowId).getSteps({ - account, - contracts, - request: flow.request, - wagmiConfig, - }); + const newFlow = { + ...flow, + steps: steps.map((id) => ({ + id, + error: null, + txHash: null, + txStatus: "idle" as const, + })), + }; + + setFlowAndStatus({ flow: newFlow }); + FlowContextStorage.set(newFlow); }, }); - // update the flow with the newly received steps - useEffect(() => { - if (flow && flowStatus === "awaiting-steps" && stepsQuery.data) { - setState((state) => ( - (!state.flow || !stepsQuery.data) ? state : { - ...state, - flow: { - ...state.flow, - steps: stepsQuery.data.map((id) => ({ - id, - error: null, - txHash: null, - })), - }, - } - )); - } - }, [ - flowStatus, - stepsQuery.data?.join(""), - currentStepIndex, - ]); - // update the active flow when the account changes useEffect(() => { // no account: no active flow if (!account.address) { if (flow) { - setState({ flow: null, flowStatus: null }); + setFlowAndStatus({ flow: null }); } return; } // no flow: try to restore from local storage if (!flow) { - const flow = flowStateStorage.get() ?? null; - const flowStatus = flow ? "ready" : null; + const flow = FlowContextStorage.get() ?? null; if (flow?.account === account.address) { - setState({ flow, flowStatus }); + setFlowAndStatus({ flow }); } return; } // flow exists, but different account: no active flow if (account.address !== flow.account) { - setState({ flow: null, flowStatus: null }); + setFlowAndStatus({ flow: null }); } }, [account, flow]); - // store flow in local storage on every update - useEffect(() => { - if (currentStepIndex > -1 && flow) { - flowStateStorage.set(flow); - } - }, [currentStepIndex, flow]); - const contractWrite = useWriteContract(); - const txReceipt = useWaitForTransactionReceipt({ + const txReceipt = useTransactionReceipt({ hash: contractWrite.data, }); + const flowDeclaration = flow && getFlowDeclaration(flow.request.flowId); + const signAndSend = useCallback(async () => { const currentStepId = flow?.steps?.[currentStepIndex]?.id; - if (!currentStepId || currentStepIndex < 0 || !account) { + if (!currentStepId || currentStepIndex < 0 || !account || !flow || !flowDeclaration) { return; } - const params = await getFlowDeclaration(flow.request.flowId).writeContractParams({ + updateStep(currentStepIndex, { + error: null, + txHash: null, + txStatus: "awaiting-signature", + }); + + const params = await flowDeclaration.writeContractParams({ contracts, request: flow.request, stepId: currentStepId, }); if (params) { - contractWrite.writeContractAsync(params); + contractWrite.writeContract(params, { + onError: (err) => { + updateStep(currentStepIndex, { + error: `${err.name}: ${err.message}`, + txHash: null, + txStatus: "error", + }); + }, + }); } }, [ account, @@ -281,106 +346,38 @@ export function TransactionFlow({ children }: { children: ReactNode }) { contracts, currentStepIndex, flow, + flowDeclaration, + updateStep, ]); - // update the flow status when the contract write status changes - useEffect(() => { - if (contractWrite.status === "idle") { - return; - } - - if (contractWrite.status === "error") { - const error = `${contractWrite.error.name}: ${contractWrite.error.message}`; - - contractWrite.reset(); - - setState((state) => { - if (!state.flow || !state.flow.steps) { - return state; - } - - const steps = [...state.flow.steps]; - - steps[currentStepIndex] = { - ...steps[currentStepIndex], - error, - }; - - return { - ...state, - flow: { ...state.flow, steps }, - }; - }); - } + const totalSteps = flow?.steps?.length ?? 0; - if (contractWrite.status === "success") { + // handle transaction receipt + useEffect(() => { + if (txReceipt.status !== "pending") { contractWrite.reset(); - - setState((state) => { - if (!state.flow || !state.flow.steps) { - return state; - } - - const steps = [...state.flow.steps]; - - steps[currentStepIndex] = { - ...steps[currentStepIndex], - error: null, - txHash: contractWrite.data, - }; - - return { - ...state, - flow: { ...state.flow, steps }, - }; - }); } - }, [ - contractWrite.error, - contractWrite.reset, - contractWrite.status, - ]); - - useEffect(() => { if (txReceipt.status === "success") { - setState((state) => { - if (!state.flow || !state.flow.steps) { - return state; - } - - const steps = [...state.flow.steps]; - const step = steps[currentStepIndex]; - steps[currentStepIndex] = { - ...step, - txHash: txReceipt.data.transactionHash, - }; - - return { - ...state, - flow: { ...state.flow, steps }, - }; + updateStep(currentStepIndex, { + error: null, + txHash: txReceipt.data.transactionHash, + txStatus: "confirmed", }); } if (txReceipt.status === "error") { - setState((state) => { - if (!state.flow || !state.flow.steps) { - return state; - } - - const steps = [...state.flow.steps]; - const step = steps[currentStepIndex]; - steps[currentStepIndex] = { - ...step, - error: `${txReceipt.error.name}: ${txReceipt.error.message}`, - }; - - return { - ...state, - flow: { ...state.flow, steps }, - }; + updateStep(currentStepIndex, { + error: txReceipt.error.message, + txHash: null, + txStatus: "error", }); } - }, [txReceipt]); + }, [ + contractWrite, + currentStepIndex, + totalSteps, + txReceipt, + updateStep, + ]); return ( @@ -397,15 +395,78 @@ export function TransactionFlow({ children }: { children: ReactNode }) { ); } +function useSteps({ + flow, + enabled, + account, + contracts, + wagmiConfig, + onSteps, +}: { + flow: FlowContext | null; + enabled: boolean; + account: ReturnType; + contracts: ReturnType; + wagmiConfig: ReturnType; + onSteps: (steps: string[]) => void; +}) { + const steps = useQuery({ + enabled, + queryKey: [ + "transaction-flow-steps", + jsonStringifyWithDnum(flow?.request), + account.address, + ], + queryFn: async () => { + if (!flow || !account.address || flow.account !== account.address) { + return null; + } + + const flowDeclaration = getFlowDeclaration(flow.request.flowId); + return flowDeclaration.getSteps({ + account, + contracts, + request: flow.request, + wagmiConfig, + }); + }, + }); + + useEffect(() => { + if (!flow || !steps.data) { + return; + } + + const newSteps = steps.data.map((id) => ({ + id, + error: null, + txHash: null, + })); + + const stepsKey = flow.steps?.map((s) => s.id).join(""); + const newStepsKey = newSteps.map((s) => s.id).join(""); + + if (stepsKey !== newStepsKey) { + onSteps(steps.data); + } + }, [steps.data, flow, onSteps]); +} + export function useTransactionFlow() { return useContext(TransactionFlowContext); } -const flowStateStorage = { - set(flow: FlowState) { +function getCurrentStepIndex(flow: FlowContext | null) { + if (!flow?.steps) return 0; + const index = flow.steps.findIndex((step) => step.txHash === null); + return index === -1 ? flow.steps.length - 1 : index; +} + +const FlowContextStorage = { + set(flow: FlowContext) { localStorage.setItem(TRANSACTION_FLOW_KEY, jsonStringifyWithDnum(flow)); }, - get(): FlowState | null { + get(): FlowContext | null { try { const storedState = localStorage.getItem(TRANSACTION_FLOW_KEY) ?? ""; const { request, steps, account } = v.parse(FlowStateSchema, jsonParseWithDnum(storedState)); diff --git a/frontend/app/src/subgraph-hooks.ts b/frontend/app/src/subgraph-hooks.ts index 42ebe0ae..50c718fe 100644 --- a/frontend/app/src/subgraph-hooks.ts +++ b/frontend/app/src/subgraph-hooks.ts @@ -1,33 +1,47 @@ -import type { Address, PositionLoan, TroveId } from "@/src/types"; +import type { Address, PositionLoan, PrefixedTroveId } from "@/src/types"; import { getBuiltGraphSDK } from "@/.graphclient"; import { ACCOUNT_POSITIONS } from "@/src/demo-mode"; import { dnum18 } from "@/src/dnum-utils"; import { DEMO_MODE } from "@/src/env"; import { getCollateralFromTroveSymbol } from "@/src/liquity-utils"; -import { isPositionLoan, isTroveId } from "@/src/types"; +import { isCollIndex, isPositionLoan, isPrefixedtroveId, isTroveId } from "@/src/types"; import { sleep } from "@/src/utils"; import { useQuery } from "@tanstack/react-query"; +const REFETCH_INTERVAL = 10_000; + const graphSdk = getBuiltGraphSDK(); -function subgraphTroveToLoan( - trove: Awaited>["troves"][0], -): PositionLoan { - if (!isTroveId(trove.id)) { - throw new Error(`Invalid trove ID: ${trove.id}`); - } - const collSymbol = getCollateralFromTroveSymbol(trove.collateral.token.symbol); - if (!collSymbol) { - throw new Error(`Invalid collateral symbol: ${collSymbol}`); - } - return { - type: "borrow", - borrowed: dnum18(trove.debt), - collateral: collSymbol, - deposit: dnum18(trove.deposit), - interestRate: dnum18(trove.interestRate), - troveId: trove.id, +export let useTroveCount = (account?: Address, collIndex?: number) => { + return useQuery({ + queryKey: ["TrovesCount", account, collIndex], + queryFn: async () => { + if (!account) { + return null; + } + const { borrowerInfo } = await graphSdk.TrovesCount({ id: account.toLowerCase() }); + return collIndex === undefined + ? borrowerInfo?.troves ?? 0 + : borrowerInfo?.trovesByCollateral[collIndex] ?? null; + }, + refetchInterval: REFETCH_INTERVAL, + }); +}; + +if (DEMO_MODE) { + useTroveCount = (account?: Address, _collIndex?: number) => { + return useQuery({ + queryKey: ["TrovesCount", account], + queryFn: async () => { + if (!account) { + return null; + } + return Object.values(ACCOUNT_POSITIONS) + .filter(isPositionLoan) + .length; + }, + }); }; } @@ -41,6 +55,7 @@ export let useLoansByAccount = (account?: Address) => { const { troves } = await graphSdk.TrovesByAccount({ account }); return troves.map(subgraphTroveToLoan); }, + refetchInterval: REFETCH_INTERVAL, }); }; @@ -58,33 +73,35 @@ if (DEMO_MODE) { }; } -export let useLoanById = (troveId?: TroveId | null) => { +export let useLoanById = (id?: PrefixedTroveId | null) => { return useQuery({ - queryKey: ["TroveById", troveId], + queryKey: ["TroveById", id], queryFn: async () => { - if (!troveId || !isTroveId(troveId)) { + if (!id || !isPrefixedtroveId(id)) { return null; } await sleep(500); - const { trove } = await graphSdk.TroveById({ id: troveId }); - return trove && isTroveId(trove.id) + const { trove } = await graphSdk.TroveById({ id }); + return trove ? subgraphTroveToLoan(trove) : null; }, + refetchInterval: REFETCH_INTERVAL, }); }; if (DEMO_MODE) { - useLoanById = (troveId?: TroveId | null) => { + useLoanById = (id?: PrefixedTroveId | null) => { return useQuery({ - queryKey: ["TroveById", troveId], + queryKey: ["TroveById", id], queryFn: async () => { - if (!troveId || !isTroveId(troveId)) { + if (!id || !isPrefixedtroveId(id)) { return null; } - for (const position of ACCOUNT_POSITIONS) { - if (isPositionLoan(position) && position.troveId === troveId) { - return position; + await sleep(500); + for (const pos of ACCOUNT_POSITIONS) { + if (isPositionLoan(pos) && `${pos.collIndex}:${pos.troveId}` === id) { + return pos; } } return null; @@ -92,3 +109,28 @@ if (DEMO_MODE) { }); }; } + +function subgraphTroveToLoan( + trove: Awaited>["troves"][0], +): PositionLoan { + if (!isTroveId(trove.troveId)) { + throw new Error(`Invalid trove ID: ${trove.id} / ${trove.troveId}`); + } + const collSymbol = getCollateralFromTroveSymbol(trove.collateral.token.symbol); + if (!collSymbol) { + throw new Error(`Invalid collateral symbol: ${collSymbol}`); + } + const collIndex = trove.collateral.collIndex; + if (!isCollIndex(collIndex)) { + throw new Error(`Invalid collateral index: ${collIndex}`); + } + return { + type: "borrow", + borrowed: dnum18(trove.debt), + collateral: collSymbol, + deposit: dnum18(trove.deposit), + interestRate: dnum18(trove.interestRate), + troveId: trove.troveId, + collIndex, + }; +} diff --git a/frontend/app/src/subgraph-queries.graphql b/frontend/app/src/subgraph-queries.graphql index 44a43cad..0b6f79f8 100644 --- a/frontend/app/src/subgraph-queries.graphql +++ b/frontend/app/src/subgraph-queries.graphql @@ -1,6 +1,7 @@ query TrovesByAccount($account: Bytes!) { - troves(where: { borrower: $account }) { + troves(where: { borrower: $account, closedAt: null }) { id + troveId borrower debt deposit @@ -15,13 +16,22 @@ query TrovesByAccount($account: Bytes!) { name } minCollRatio + collIndex } } } +query TrovesCount($id: ID!) { + borrowerInfo(id: $id) { + troves + trovesByCollateral + } +} + query TroveById($id: ID!) { trove(id: $id) { id + troveId borrower debt deposit @@ -36,6 +46,7 @@ query TroveById($id: ID!) { name } minCollRatio + collIndex } } } diff --git a/frontend/app/src/tx-flows/closeLoanPosition.tsx b/frontend/app/src/tx-flows/closeLoanPosition.tsx new file mode 100644 index 00000000..9d4ee463 --- /dev/null +++ b/frontend/app/src/tx-flows/closeLoanPosition.tsx @@ -0,0 +1,133 @@ +import type { LoadingState } from "@/src/screens/TransactionsScreen/TransactionsScreen"; +import type { FlowDeclaration } from "@/src/services/TransactionFlow"; + +import { fmtnum } from "@/src/formatting"; +import { useCollateral } from "@/src/liquity-utils"; +import { parsePrefixedTroveId } from "@/src/liquity-utils"; +import { LoanCard } from "@/src/screens/TransactionsScreen/LoanCard"; +import { TransactionDetailsRow } from "@/src/screens/TransactionsScreen/TransactionsScreen"; +import { useLoanById } from "@/src/subgraph-hooks"; +import { vCollIndex, vPrefixedTroveId } from "@/src/valibot-utils"; +import { match, P } from "ts-pattern"; +import * as v from "valibot"; + +const FlowIdSchema = v.literal("closeLoanPosition"); + +const RequestSchema = v.object({ + flowId: FlowIdSchema, + + backLink: v.union([ + v.null(), + v.tuple([ + v.string(), // path + v.string(), // label + ]), + ]), + successLink: v.tuple([ + v.string(), // path + v.string(), // label + ]), + successMessage: v.string(), + + collIndex: vCollIndex(), + prefixedTroveId: vPrefixedTroveId(), +}); + +export type Request = v.InferOutput; + +type Step = "closeLoanPosition"; + +const stepNames: Record = { + closeLoanPosition: "Close Position", +}; + +export const closeLoanPosition: FlowDeclaration = { + title: "Review & Send Transaction", + subtitle: ( +
+ You are repaying your debt and closing this position.
+ The deposit will be returned to your wallet +
+ ), + + Summary({ flow }) { + const loan = useLoanById(flow.request.prefixedTroveId); + + const loadingState = match(loan) + .returnType() + .with({ status: "error" }, () => "error") + .with({ status: "pending" }, () => "loading") + .with({ data: null }, () => "not-found") + .with({ data: P.nonNullable }, () => "success") + .otherwise(() => "error"); + + return ( + {}} + /> + ); + }, + + Details({ flow }) { + const { request } = flow; + const collateral = useCollateral(request.collIndex); + const loan = useLoanById(request.prefixedTroveId); + + return loan.data && ( + <> + + {fmtnum(loan.data.borrowed, 4)} BOLD +
, + ]} + /> + + {fmtnum(loan.data.deposit, "2z")} {collateral.symbol} +
, + ]} + /> + + ); + }, + getStepName(stepid) { + return stepNames[stepid]; + }, + async getSteps() { + return ["closeLoanPosition"]; + }, + parseRequest(request) { + return v.parse(RequestSchema, request); + }, + async writeContractParams({ contracts, request, stepId }) { + const collateral = contracts.collaterals[request.collIndex]; + const { BorrowerOperations } = collateral.contracts; + + if (!BorrowerOperations) { + throw new Error(`Collateral ${collateral.symbol} not supported`); + } + + if (stepId === "closeLoanPosition") { + const { troveId } = parsePrefixedTroveId(request.prefixedTroveId); + + return { + ...BorrowerOperations, + functionName: "closeTrove" as const, + args: [troveId], + }; + } + return null; + }, +}; diff --git a/frontend/app/src/tx-flows/openLoanPosition.ts b/frontend/app/src/tx-flows/openLoanPosition.ts deleted file mode 100644 index 4c2c609f..00000000 --- a/frontend/app/src/tx-flows/openLoanPosition.ts +++ /dev/null @@ -1,98 +0,0 @@ -import type { FlowDeclaration } from "@/src/services/TransactionFlow"; - -import { ETH_GAS_COMPENSATION } from "@/src/constants"; -import { getCollateralContracts } from "@/src/contracts"; -import { ADDRESS_ZERO } from "@/src/eth-utils"; -import { vAddress, vDnum } from "@/src/valibot-utils"; -import * as dn from "dnum"; -import * as v from "valibot"; -import { readContract } from "wagmi/actions"; - -const FlowIdSchema = v.literal("openLoanPosition"); - -const RequestSchema = v.object({ - flowId: FlowIdSchema, - collIndex: v.number(), - owner: vAddress(), - ownerIndex: v.number(), - collAmount: vDnum(), - boldAmount: vDnum(), - upperHint: vDnum(), - lowerHint: vDnum(), - annualInterestRate: vDnum(), - maxUpfrontFee: vDnum(), -}); - -export type Request = v.InferOutput; - -export const openLoanPosition: FlowDeclaration = { - getSteps: async function getSteps({ - account, - contracts, - request, - wagmiConfig, - }) { - const collSymbol = contracts.collaterals[request.collIndex][0]; - const { BorrowerOperations, Token } = getCollateralContracts(collSymbol, contracts.collaterals) ?? {}; - - if (!BorrowerOperations || !Token) { - throw new Error(`Collateral ${collSymbol} not supported`); - } - - const allowance = await readContract(wagmiConfig, { - ...Token, - functionName: "allowance", - args: [ - account.address ?? ADDRESS_ZERO, - BorrowerOperations.address, - ], - }); - - const isApproved = !dn.gt( - dn.add(request.collAmount, ETH_GAS_COMPENSATION), - [allowance ?? 0n, 18], - ); - - return isApproved ? ["openTrove"] : ["approve", "openTrove"]; - }, - parseRequest: (request): Request => { - return v.parse(RequestSchema, request); - }, - writeContractParams: async ({ contracts, request, stepId }) => { - const collSymbol = contracts.collaterals[request.collIndex][0]; - const { BorrowerOperations, Token } = getCollateralContracts(collSymbol, contracts.collaterals) ?? {}; - - if (!BorrowerOperations || !Token) { - throw new Error(`Collateral ${collSymbol} not supported`); - } - - if (stepId === "approve") { - const amount = dn.add(request.collAmount, ETH_GAS_COMPENSATION); - return { - ...Token, - functionName: "approve" as const, - args: [ - BorrowerOperations.address, - amount[0], - ], - }; - } - if (stepId === "openTrove") { - return { - ...BorrowerOperations, - functionName: "openTrove" as const, - args: [ - request.owner ?? ADDRESS_ZERO, - request.ownerIndex, - request.collAmount[0], - request.boldAmount[0], - request.upperHint[0], - request.lowerHint[0], - request.annualInterestRate[0], - request.maxUpfrontFee[0], - ], - }; - } - return null; - }, -}; diff --git a/frontend/app/src/tx-flows/openLoanPosition.tsx b/frontend/app/src/tx-flows/openLoanPosition.tsx new file mode 100644 index 00000000..48479805 --- /dev/null +++ b/frontend/app/src/tx-flows/openLoanPosition.tsx @@ -0,0 +1,218 @@ +import type { FlowDeclaration } from "@/src/services/TransactionFlow"; + +import { ETH_GAS_COMPENSATION } from "@/src/constants"; +import { dnum18 } from "@/src/dnum-utils"; +import { ADDRESS_ZERO } from "@/src/eth-utils"; +import { fmtnum } from "@/src/formatting"; +import { useCollateral } from "@/src/liquity-utils"; +import { LoanCard } from "@/src/screens/TransactionsScreen/LoanCard"; +import { TransactionDetailsRow } from "@/src/screens/TransactionsScreen/TransactionsScreen"; +import { usePrice } from "@/src/services/Prices"; +import { vAddress, vCollIndex, vDnum } from "@/src/valibot-utils"; +import * as dn from "dnum"; +import * as v from "valibot"; +import { readContract } from "wagmi/actions"; + +const FlowIdSchema = v.literal("openLoanPosition"); + +const RequestSchema = v.object({ + flowId: FlowIdSchema, + backLink: v.union([ + v.null(), + v.tuple([ + v.string(), // path + v.string(), // label + ]), + ]), + successLink: v.tuple([ + v.string(), // path + v.string(), // label + ]), + successMessage: v.string(), + + collIndex: vCollIndex(), + owner: vAddress(), + ownerIndex: v.number(), + collAmount: vDnum(), + boldAmount: vDnum(), + upperHint: vDnum(), + lowerHint: vDnum(), + annualInterestRate: vDnum(), + maxUpfrontFee: vDnum(), +}); + +export type Request = v.InferOutput; + +type Step = "wrapEth" | "approve" | "openTrove"; + +const stepNames: Record = { + wrapEth: "Wrap ETH", + approve: "Approve", + openTrove: "Open Position", +}; + +export const openLoanPosition: FlowDeclaration = { + title: "Review & Send Transaction", + subtitle: "Please review your borrow position before confirming", + + Summary({ flow }) { + const { symbol } = useCollateral(flow.request.collIndex); + return ( + {}} + /> + ); + }, + + Details({ flow }) { + const { request } = flow; + const collateral = useCollateral(flow.request.collIndex); + const collPrice = usePrice(collateral.symbol); + const boldPrice = usePrice("BOLD"); + return ( + <> + + + + + ); + }, + + async getSteps({ + account, + contracts, + request, + wagmiConfig, + }) { + const collateral = contracts.collaterals[request.collIndex]; + const { BorrowerOperations, Token } = collateral.contracts; + + if (!BorrowerOperations || !Token) { + throw new Error(`Collateral ${collateral.symbol} not supported`); + } + + const allowance = dnum18( + await readContract(wagmiConfig, { + ...Token, + functionName: "allowance", + args: [ + account.address ?? ADDRESS_ZERO, + BorrowerOperations.address, + ], + }), + ); + + const wethBalance = collateral.symbol !== "ETH" ? null : dnum18( + await readContract(wagmiConfig, { + ...Token, + functionName: "balanceOf", + args: [account.address ?? ADDRESS_ZERO], + }), + ); + + const isApproved = !dn.gt( + dn.add(request.collAmount, ETH_GAS_COMPENSATION), + allowance, + ); + + const steps: Step[] = []; + + if (wethBalance && dn.lt(wethBalance, request.collAmount)) { + steps.push("wrapEth"); + } + + if (!isApproved) { + steps.push("approve"); + } + + return [...steps, "openTrove"]; + }, + + getStepName(stepId) { + return stepNames[stepId]; + }, + + parseRequest(request) { + return v.parse(RequestSchema, request); + }, + + async writeContractParams({ contracts, request, stepId }) { + const collateral = contracts.collaterals[request.collIndex]; + const { BorrowerOperations, Token } = collateral.contracts; + + if (!BorrowerOperations || !Token) { + throw new Error(`Collateral ${collateral.symbol} not supported`); + } + + if (stepId === "wrapEth") { + return { + ...contracts.WETH, + functionName: "deposit" as const, + args: [], + value: request.collAmount[0], + }; + } + + if (stepId === "approve") { + const amount = dn.add(request.collAmount, ETH_GAS_COMPENSATION); + return { + ...Token, + functionName: "approve" as const, + args: [ + BorrowerOperations.address, + amount[0], + ], + }; + } + + if (stepId === "openTrove") { + return { + ...BorrowerOperations, + functionName: "openTrove" as const, + args: [ + request.owner ?? ADDRESS_ZERO, + request.ownerIndex, + request.collAmount[0], + request.boldAmount[0], + request.upperHint[0], + request.lowerHint[0], + request.annualInterestRate[0], + request.maxUpfrontFee[0], + ADDRESS_ZERO, + ADDRESS_ZERO, + ADDRESS_ZERO, + ], + }; + } + return null; + }, +}; diff --git a/frontend/app/src/tx-flows/repayAndCloseLoanPosition.ts b/frontend/app/src/tx-flows/repayAndCloseLoanPosition.ts deleted file mode 100644 index 4367b6c1..00000000 --- a/frontend/app/src/tx-flows/repayAndCloseLoanPosition.ts +++ /dev/null @@ -1,44 +0,0 @@ -import type { FlowDeclaration } from "@/src/services/TransactionFlow"; - -import { getCollateralContracts } from "@/src/contracts"; -import { getTroveId } from "@/src/liquity-utils"; -import { vAddress } from "@/src/valibot-utils"; -import * as v from "valibot"; - -const FlowIdSchema = v.literal("repayAndCloseLoanPosition"); - -const RequestSchema = v.object({ - flowId: FlowIdSchema, - collIndex: v.number(), - owner: vAddress(), - ownerIndex: v.number(), -}); - -export type Request = v.InferOutput; - -export const repayAndCloseLoanPosition: FlowDeclaration = { - getSteps: async function getSteps() { - return ["closeTrove"]; - }, - parseRequest: (request): Request => { - return v.parse(RequestSchema, request); - }, - writeContractParams: async ({ contracts, request, stepId }) => { - const collSymbol = contracts.collaterals[request.collIndex][0]; - const { BorrowerOperations } = getCollateralContracts(collSymbol, contracts.collaterals) ?? {}; - - if (!BorrowerOperations) { - throw new Error(`Collateral ${collSymbol} not supported`); - } - - if (stepId === "closeTrove") { - const troveId = getTroveId(request.owner, request.ownerIndex); - return { - ...BorrowerOperations, - functionName: "closeTrove" as const, - args: [troveId], - }; - } - return null; - }, -}; diff --git a/frontend/app/src/tx-flows/updateLoanInterestRate.tsx b/frontend/app/src/tx-flows/updateLoanInterestRate.tsx new file mode 100644 index 00000000..cba6b21b --- /dev/null +++ b/frontend/app/src/tx-flows/updateLoanInterestRate.tsx @@ -0,0 +1,129 @@ +import type { LoadingState } from "@/src/screens/TransactionsScreen/TransactionsScreen"; +import type { FlowDeclaration } from "@/src/services/TransactionFlow"; + +import { fmtnum } from "@/src/formatting"; +import { parsePrefixedTroveId } from "@/src/liquity-utils"; +import { LoanCard } from "@/src/screens/TransactionsScreen/LoanCard"; +import { TransactionDetailsRow } from "@/src/screens/TransactionsScreen/TransactionsScreen"; +import { useLoanById } from "@/src/subgraph-hooks"; +import { vAddress, vCollIndex, vDnum, vPrefixedTroveId } from "@/src/valibot-utils"; +import * as dn from "dnum"; +import { match, P } from "ts-pattern"; +import * as v from "valibot"; + +const FlowIdSchema = v.literal("updateLoanInterestRate"); + +const RequestSchema = v.object({ + flowId: FlowIdSchema, + + backLink: v.union([ + v.null(), + v.tuple([ + v.string(), // path + v.string(), // label + ]), + ]), + successLink: v.tuple([ + v.string(), // path + v.string(), // label + ]), + successMessage: v.string(), + + collIndex: vCollIndex(), + interestRate: vDnum(), + lowerHint: vDnum(), + maxUpfrontFee: vDnum(), + owner: vAddress(), + prefixedTroveId: vPrefixedTroveId(), + upperHint: vDnum(), +}); + +export type Request = v.InferOutput; + +type Step = "adjustInterestRate"; + +const stepNames: Record = { + adjustInterestRate: "Update Interest Rate", +}; + +export const updateLoanInterestRate: FlowDeclaration = { + title: "Review & Confirm", + subtitle: "Please review the changes of your borrow position before confirming", + Summary({ flow }) { + const loan = useLoanById(flow.request.prefixedTroveId); + + const loadingState = match(loan) + .returnType() + .with({ status: "error" }, () => "error") + .with({ status: "pending" }, () => "loading") + .with({ data: null }, () => "not-found") + .with({ data: P.nonNullable }, () => "success") + .otherwise(() => "error"); + + return ( + {}} + /> + ); + }, + Details({ flow }) { + const { request } = flow; + + const loan = useLoanById(flow.request.prefixedTroveId); + const boldPerYear = dn.mul(loan.data?.borrowed ?? 0n, request.interestRate); + + return ( + + {fmtnum(request.interestRate, "full", 100)}% + , +
+ ~{fmtnum(boldPerYear, 4)} BOLD per year +
, + ]} + /> + ); + }, + getStepName(stepid) { + return stepNames[stepid]; + }, + async getSteps() { + return ["adjustInterestRate"]; + }, + parseRequest(request) { + return v.parse(RequestSchema, request); + }, + async writeContractParams({ contracts, request, stepId }) { + const collateral = contracts.collaterals[request.collIndex]; + const { BorrowerOperations } = collateral.contracts; + + if (!BorrowerOperations) { + throw new Error(`Collateral ${collateral.symbol} not supported`); + } + + if (stepId === "adjustInterestRate") { + const { troveId } = parsePrefixedTroveId(request.prefixedTroveId); + return { + ...BorrowerOperations, + functionName: "adjustTroveInterestRate" as const, + args: [ + troveId, + request.interestRate[0], + request.upperHint[0], + request.lowerHint[0], + request.maxUpfrontFee[0], + ], + }; + } + return null; + }, +}; diff --git a/frontend/app/src/tx-flows/updateLoanPosition.ts b/frontend/app/src/tx-flows/updateLoanPosition.ts deleted file mode 100644 index f0bd498d..00000000 --- a/frontend/app/src/tx-flows/updateLoanPosition.ts +++ /dev/null @@ -1,101 +0,0 @@ -import type { FlowDeclaration } from "@/src/services/TransactionFlow"; - -import { ETH_GAS_COMPENSATION } from "@/src/constants"; -import { getCollateralContracts } from "@/src/contracts"; -import { ADDRESS_ZERO } from "@/src/eth-utils"; -import { getTroveId } from "@/src/liquity-utils"; -import { vAddress, vDnum } from "@/src/valibot-utils"; -import * as dn from "dnum"; -import * as v from "valibot"; -import { readContract } from "wagmi/actions"; - -const FlowIdSchema = v.literal("updateLoanPosition"); - -const RequestSchema = v.object({ - flowId: FlowIdSchema, - collIndex: v.number(), - owner: vAddress(), - ownerIndex: v.number(), - collChange: vDnum(), - boldChange: vDnum(), - maxUpfrontFee: vDnum(), -}); - -export type Request = v.InferOutput; - -export const updateLoanPosition: FlowDeclaration = { - getSteps: async function getSteps({ - account, - contracts, - request, - wagmiConfig, - }) { - // no need for approval if collateral change is negative - if (!dn.gt(request.collChange, 0)) { - return ["adjustTrove"]; - } - - const collSymbol = contracts.collaterals[request.collIndex][0]; - const { BorrowerOperations, Token } = getCollateralContracts(collSymbol, contracts.collaterals) ?? {}; - - if (!BorrowerOperations || !Token) { - throw new Error(`Collateral ${collSymbol} not supported`); - } - - const allowance = await readContract(wagmiConfig, { - ...Token, - functionName: "allowance", - args: [ - account.address ?? ADDRESS_ZERO, - BorrowerOperations.address, - ], - }); - - const isApproved = !dn.gt( - dn.add(request.collChange, ETH_GAS_COMPENSATION), - [allowance ?? 0n, 18], - ); - - return isApproved ? ["adjustTrove"] : ["approve", "adjustTrove"]; - }, - parseRequest: (request): Request => { - return v.parse(RequestSchema, request); - }, - writeContractParams: async ({ contracts, request, stepId }) => { - const collSymbol = contracts.collaterals[request.collIndex][0]; - const { BorrowerOperations, Token } = getCollateralContracts(collSymbol, contracts.collaterals) ?? {}; - - if (!BorrowerOperations || !Token) { - throw new Error(`Collateral ${collSymbol} not supported`); - } - - if (stepId === "approve") { - const amount = dn.add(request.collChange, ETH_GAS_COMPENSATION); - return { - ...Token, - functionName: "approve" as const, - args: [ - BorrowerOperations.address, - amount[0], - ], - }; - } - - if (stepId === "adjustTrove") { - const troveId = getTroveId(request.owner, request.ownerIndex); - return { - ...BorrowerOperations, - functionName: "adjustTrove" as const, - args: [ - troveId, - request.collChange[0], - !dn.lt(request.collChange, 0n), - request.boldChange[0], - !dn.lt(request.boldChange, 0n), - request.maxUpfrontFee[0], - ], - }; - } - return null; - }, -}; diff --git a/frontend/app/src/tx-flows/updateLoanPosition.tsx b/frontend/app/src/tx-flows/updateLoanPosition.tsx new file mode 100644 index 00000000..8f46cc77 --- /dev/null +++ b/frontend/app/src/tx-flows/updateLoanPosition.tsx @@ -0,0 +1,232 @@ +import type { LoadingState } from "@/src/screens/TransactionsScreen/TransactionsScreen"; +import type { FlowDeclaration } from "@/src/services/TransactionFlow"; + +import { ETH_GAS_COMPENSATION } from "@/src/constants"; +import { ADDRESS_ZERO } from "@/src/eth-utils"; +import { fmtnum } from "@/src/formatting"; +import { useCollateral } from "@/src/liquity-utils"; +import { parsePrefixedTroveId } from "@/src/liquity-utils"; +import { LoanCard } from "@/src/screens/TransactionsScreen/LoanCard"; +import { TransactionDetailsRow } from "@/src/screens/TransactionsScreen/TransactionsScreen"; +import { usePrice } from "@/src/services/Prices"; +import { useLoanById } from "@/src/subgraph-hooks"; +import { vAddress, vCollIndex, vDnum, vPrefixedTroveId } from "@/src/valibot-utils"; +import * as dn from "dnum"; +import { match, P } from "ts-pattern"; +import * as v from "valibot"; +import { readContract } from "wagmi/actions"; + +const FlowIdSchema = v.literal("updateLoanPosition"); + +const RequestSchema = v.object({ + flowId: FlowIdSchema, + backLink: v.union([ + v.null(), + v.tuple([ + v.string(), // path + v.string(), // label + ]), + ]), + successLink: v.tuple([ + v.string(), // path + v.string(), // label + ]), + successMessage: v.string(), + + boldChange: vDnum(), + collChange: vDnum(), + collIndex: vCollIndex(), + maxUpfrontFee: vDnum(), + owner: vAddress(), + prefixedTroveId: vPrefixedTroveId(), +}); + +export type Request = v.InferOutput; + +type Step = "approve" | "adjustTrove"; + +const stepNames: Record = { + approve: "Approve", + adjustTrove: "Update Position", +}; + +export const updateLoanPosition: FlowDeclaration = { + title: "Review & Send Transaction", + subtitle: "Please review the changes of your borrow position before confirming", + Summary({ flow }) { + const { symbol } = useCollateral(flow.request.collIndex); + const loan = useLoanById(flow.request.prefixedTroveId); + const { troveId } = parsePrefixedTroveId(flow.request.prefixedTroveId); + const loadingState = match(loan) + .returnType() + .with({ status: "error" }, () => "error") + .with({ status: "pending" }, () => "loading") + .with({ data: null }, () => "not-found") + .with({ data: P.nonNullable }, () => "success") + .otherwise(() => "error"); + + const newDeposit = dn.add(loan.data?.deposit ?? 0n, flow.request.collChange); + const newBorrowed = dn.add(loan.data?.borrowed ?? 0n, flow.request.boldChange); + + const newLoan = !loan.data ? null : { + troveId, + borrowed: newBorrowed, + collIndex: flow.request.collIndex, + collateral: symbol, + deposit: newDeposit, + interestRate: loan.data.interestRate, + type: "borrow" as const, + }; + + const prevLoan = !newLoan || !loan.data ? null : { + ...newLoan, + borrowed: loan.data.borrowed, + deposit: loan.data.deposit, + }; + + return ( + {}} + /> + ); + }, + Details({ flow }) { + const { request } = flow; + const collateral = useCollateral(flow.request.collIndex); + const collPrice = usePrice(collateral.symbol); + const boldPrice = usePrice("BOLD"); + + const collChangeUnsigned = dn.abs(request.collChange); + const boldChangeUnsigned = dn.abs(request.boldChange); + + return ( + <> + + {fmtnum(collChangeUnsigned)} {collateral.name} + , + collPrice && ( +
+ ${fmtnum(dn.mul(collChangeUnsigned, collPrice))} +
+ ), + ]} + /> + + {fmtnum(boldChangeUnsigned)} BOLD + , + boldPrice && ( +
+ ${fmtnum(dn.mul(boldChangeUnsigned, boldPrice))} +
+ ), + ]} + /> + + ); + }, + + getStepName(stepId) { + return stepNames[stepId]; + }, + + async getSteps({ + account, + contracts, + request, + wagmiConfig, + }) { + // no need for approval if collateral change is negative + if (!dn.gt(request.collChange, 0)) { + return ["adjustTrove"]; + } + + const collateral = contracts.collaterals[request.collIndex]; + const { BorrowerOperations, Token } = collateral.contracts; + + if (!BorrowerOperations || !Token) { + throw new Error(`Collateral ${collateral.symbol} not supported`); + } + + const allowance = await readContract(wagmiConfig, { + ...Token, + functionName: "allowance", + args: [ + account.address ?? ADDRESS_ZERO, + BorrowerOperations.address, + ], + }); + + const isApproved = !dn.gt( + dn.add(request.collChange, ETH_GAS_COMPENSATION), + [allowance ?? 0n, 18], + ); + + return isApproved ? ["adjustTrove"] : ["approve", "adjustTrove"]; + }, + parseRequest(request) { + return v.parse(RequestSchema, request); + }, + async writeContractParams({ contracts, request, stepId }) { + const collateral = contracts.collaterals[request.collIndex]; + const { BorrowerOperations, Token } = collateral.contracts; + + if (!BorrowerOperations || !Token) { + throw new Error(`Collateral ${collateral.symbol} not supported`); + } + + if (stepId === "approve") { + const amount = dn.add(request.collChange, ETH_GAS_COMPENSATION); + return { + ...Token, + functionName: "approve" as const, + args: [ + BorrowerOperations.address, + amount[0], + ], + }; + } + + if (stepId === "adjustTrove") { + const { troveId } = parsePrefixedTroveId(request.prefixedTroveId); + return { + ...BorrowerOperations, + functionName: "adjustTrove" as const, + args: [ + troveId, + dn.abs(request.collChange)[0], + !dn.lt(request.collChange, 0n), + dn.abs(request.boldChange)[0], + !dn.lt(request.boldChange, 0n), + request.maxUpfrontFee[0], + ], + }; + } + return null; + }, +}; diff --git a/frontend/app/src/types.ts b/frontend/app/src/types.ts index d004bc6d..f88ed6d0 100644 --- a/frontend/app/src/types.ts +++ b/frontend/app/src/types.ts @@ -6,12 +6,22 @@ export type { Address, CollateralSymbol, Dnum, Token }; export type RiskLevel = "low" | "medium" | "high"; +export type CollIndex = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; export type TroveId = `0x${string}`; +export type PrefixedTroveId = `${CollIndex}:${TroveId}`; + +export function isCollIndex(value: unknown): value is CollIndex { + return typeof value === "number" && value >= 0 && value <= 9; +} export function isTroveId(value: unknown): value is TroveId { return typeof value === "string" && /^0x[0-9a-f]+$/.test(value); } +export function isPrefixedtroveId(value: unknown): value is PrefixedTroveId { + return typeof value === "string" && /^[0-9]:0x[0-9a-f]+$/.test(value); +} + // Utility type to get type-safe entries of an object, // to be used like this: Object.entries(o) as Entries) export type Entries = { @@ -32,6 +42,7 @@ export type MenuSection = { export type PositionLoan = { type: "borrow" | "leverage"; borrowed: Dnum; + collIndex: CollIndex; collateral: CollateralSymbol; deposit: Dnum; interestRate: Dnum; diff --git a/frontend/app/src/valibot-utils.ts b/frontend/app/src/valibot-utils.ts index cd91dbc0..d8feb017 100644 --- a/frontend/app/src/valibot-utils.ts +++ b/frontend/app/src/valibot-utils.ts @@ -1,3 +1,4 @@ +import type { PrefixedTroveId } from "@/src/types"; import type { Address } from "@liquity2/uikit"; import type { Dnum } from "dnum"; @@ -13,6 +14,30 @@ export function vDnum() { return v.custom(isDnum, "not a Dnum"); } +export function vCollIndex() { + return v.union([ + v.literal(0), + v.literal(1), + v.literal(2), + v.literal(3), + v.literal(4), + v.literal(5), + v.literal(6), + v.literal(7), + v.literal(8), + v.literal(9), + ]); +} + +export function vPrefixedTroveId() { + return v.pipe( + v.string(), + v.trim(), + v.regex(/^[0-9]:0x[0-9a-f]+$/), + v.transform((value) => value as PrefixedTroveId), + ); +} + // Env var link, e.g. Etherscan|https://etherscan.io export function vEnvLink() { return v.pipe( diff --git a/frontend/uikit/src/StrongCard/StrongCard.tsx b/frontend/uikit/src/StrongCard/StrongCard.tsx index fd985154..cccb2508 100644 --- a/frontend/uikit/src/StrongCard/StrongCard.tsx +++ b/frontend/uikit/src/StrongCard/StrongCard.tsx @@ -1,4 +1,4 @@ -import type { HTMLAttributes, ReactElement, ReactNode } from "react"; +import type { CSSProperties, HTMLAttributes, ReactElement, ReactNode } from "react"; import { a, useSpring } from "@react-spring/web"; import { forwardRef, useState } from "react"; @@ -17,12 +17,14 @@ export const StrongCard = forwardRef< { contextual?: ReactNode; heading: ElementOrString | ElementOrString[]; + loading?: boolean; main?: Cell; secondary: ReactNode; } & HTMLAttributes >(function StrongCard({ contextual, heading, + loading, main, secondary, ...anchorProps @@ -50,6 +52,15 @@ export const StrongCard = forwardRef< }, }); + const loadingGradientSpring = useSpring({ + from: { progress: 0 }, + to: { progress: 1 }, + loop: true, + config: { + duration: 2_000, + }, + }); + return ( + {loading && ( + `scale3d(${p}, ${p}, 1)`), + ...{ + "--loading-angle": loadingGradientSpring.progress.to( + (p) => `${p * 360 - 45}deg`, + ), + "--loading-midpoint1": loadingGradientSpring.progress + .to([0, 0.5, 1], ["50%", "20%", "50%"]), + "--loading-midpoint2": loadingGradientSpring.progress + .to([0, 0.5, 1], ["50%", "80%", "50%"]), + } as CSSProperties, + }} + /> + )}
} + | { origin: "touch"; event: TouchEvent } + | { origin: "keyboard"; event: KeyboardEvent }; + export function Tabs({ compact, items, @@ -31,7 +36,7 @@ export function Tabs({ }: { compact?: boolean; items: TabItem[]; - onSelect: (index: number) => void; + onSelect: (index: number, context: OnSelectContext) => void; selected: number; }) { const container = useRef(null); @@ -164,7 +169,7 @@ export function Tabs({ onSelect(index)} + onSelect={(context) => onSelect(index, context)} selected={index === selected} tabItem={item} /> @@ -199,7 +204,7 @@ function Tab({ tabItem: { label, tabId, panelId }, }: { compact?: boolean; - onSelect: () => void; + onSelect: (context: Exclude) => void; selected: boolean; tabItem: TabItem; }) { @@ -219,8 +224,12 @@ function Tab({ aria-controls={panelId} aria-selected={selected} id={tabId} - onMouseDown={onSelect} - onTouchEnd={onSelect} + onMouseDown={(event) => { + onSelect({ origin: "mouse", event }); + }} + onTouchStart={(event) => { + onSelect({ origin: "touch", event }); + }} role="tab" tabIndex={selected ? 0 : -1} className={css({ @@ -257,9 +266,12 @@ function useKeyboardNavigation({ onSelect, selected, }: { - isFocused: React.MutableRefObject; + isFocused: MutableRefObject; itemsLength: number; - onSelect: (index: number) => void; + onSelect: ( + index: number, + context: Extract, + ) => void; selected: number; }) { useEffect(() => { @@ -267,14 +279,15 @@ function useKeyboardNavigation({ if (!isFocused.current) { return; } + const context = { origin: "keyboard", event } as const; if (event.key === "ArrowRight") { event.preventDefault(); - onSelect((selected + 1) % itemsLength); + onSelect((selected + 1) % itemsLength, context); return; } if (event.key === "ArrowLeft") { event.preventDefault(); - onSelect(selected === 0 ? itemsLength - 1 : selected - 1); + onSelect(selected === 0 ? itemsLength - 1 : selected - 1, context); return; } }; @@ -291,8 +304,8 @@ function useFocusSelected({ isFocused, selected, }: { - container: React.MutableRefObject; - isFocused: React.MutableRefObject; + container: MutableRefObject; + isFocused: MutableRefObject; selected: number; }) { useEffect(() => { diff --git a/frontend/uikit/src/Theme/Theme.tsx b/frontend/uikit/src/Theme/Theme.tsx index ccba3d70..0d2d5cbb 100644 --- a/frontend/uikit/src/Theme/Theme.tsx +++ b/frontend/uikit/src/Theme/Theme.tsx @@ -172,6 +172,9 @@ export const lightTheme = { riskGradient4: "#FFA12B", riskGradient5: "red:500", + loadingGradient1: "blue:50", + loadingGradient2: "blue:100", + // not used yet brandCyan: "brand:cyan", brandCoral: "brand:coral", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a6c26c7f..db93b73b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -92,6 +92,9 @@ importers: frontend/app: dependencies: + '@graphprotocol/client-cli': + specifier: ^3.0.7 + version: 3.0.7(@envelop/core@5.0.2)(@graphql-mesh/cross-helpers@0.4.6)(@graphql-mesh/store@0.102.5)(@graphql-mesh/types@0.102.5)(@graphql-mesh/utils@0.102.5)(@graphql-tools/delegate@10.0.21)(@graphql-tools/merge@9.0.7)(@graphql-tools/utils@10.5.4)(@graphql-tools/wrap@10.0.5)(@types/node@22.0.2)(@types/react@18.3.3)(graphql-tag@2.12.6)(graphql-yoga@5.7.0)(graphql@16.9.0)(react-dom@18.3.1)(react@18.3.1) '@liquity2/uikit': specifier: workspace:* version: link:../uikit @@ -104,6 +107,9 @@ importers: '@tanstack/react-query': specifier: ^5.51.16 version: 5.51.16(react@18.3.1) + '@wagmi/core': + specifier: ^2.12.2 + version: 2.13.5(@types/react@18.3.3)(react@18.3.1)(typescript@5.5.4)(viem@2.18.7) dnum: specifier: ^2.13.1 version: 2.13.1 @@ -323,9 +329,6 @@ importers: tsx: specifier: ^4.16.5 version: 4.16.5 - yaml: - specifier: ^2.5.0 - version: 2.5.0 zx: specifier: ^8.1.4 version: 8.1.4 @@ -351,6 +354,85 @@ packages: '@jridgewell/gen-mapping': 0.3.5 '@jridgewell/trace-mapping': 0.3.25 + /@apollo/client@3.11.8(@types/react@18.3.3)(graphql@16.9.0)(react-dom@18.3.1)(react@18.3.1): + resolution: {integrity: sha512-CgG1wbtMjsV2pRGe/eYITmV5B8lXUCYljB2gB/6jWTFQcrvirUVvKg7qtFdjYkQSFbIffU1IDyxgeaN81eTjbA==} + requiresBuild: true + peerDependencies: + graphql: ^15.0.0 || ^16.0.0 + graphql-ws: ^5.5.5 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0 + subscriptions-transport-ws: ^0.9.0 || ^0.11.0 + peerDependenciesMeta: + graphql-ws: + optional: true + react: + optional: true + react-dom: + optional: true + subscriptions-transport-ws: + optional: true + dependencies: + '@graphql-typed-document-node/core': 3.2.0(graphql@16.9.0) + '@wry/caches': 1.0.1 + '@wry/equality': 0.5.7 + '@wry/trie': 0.5.0 + graphql: 16.9.0 + graphql-tag: 2.12.6(graphql@16.9.0) + hoist-non-react-statics: 3.3.2 + optimism: 0.18.0 + prop-types: 15.8.1 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + rehackt: 0.1.0(@types/react@18.3.3)(react@18.3.1) + response-iterator: 0.2.6 + symbol-observable: 4.0.0 + ts-invariant: 0.10.3 + tslib: 2.6.3 + zen-observable-ts: 1.2.5 + transitivePeerDependencies: + - '@types/react' + dev: false + optional: true + + /@ardatan/relay-compiler@12.0.0(graphql@16.9.0): + resolution: {integrity: sha512-9anThAaj1dQr6IGmzBMcfzOQKTa5artjuPmw8NYK/fiGEMjADbSguBY2FMDykt+QhilR3wc9VA/3yVju7JHg7Q==} + hasBin: true + peerDependencies: + graphql: '*' + dependencies: + '@babel/core': 7.25.2 + '@babel/generator': 7.25.0 + '@babel/parser': 7.25.3 + '@babel/runtime': 7.25.0 + '@babel/traverse': 7.25.3 + '@babel/types': 7.25.2 + babel-preset-fbjs: 3.4.0(@babel/core@7.25.2) + chalk: 4.1.2 + fb-watchman: 2.0.2 + fbjs: 3.0.5 + glob: 7.2.3 + graphql: 16.9.0 + immutable: 3.7.6 + invariant: 2.2.4 + nullthrows: 1.1.1 + relay-runtime: 12.0.0 + signedsource: 1.0.0 + yargs: 15.4.1 + transitivePeerDependencies: + - encoding + - supports-color + dev: false + + /@ardatan/sync-fetch@0.0.1: + resolution: {integrity: sha512-xhlTqH0m31mnsG0tIP4ETgfSB6gXDaYYsUWTrlUV93fFQPI9dd8hE0Ot6MHLCtqgB32hwJAC3YZMWlXZw7AleA==} + engines: {node: '>=14'} + dependencies: + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + dev: false + /@babel/code-frame@7.24.2: resolution: {integrity: sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==} engines: {node: '>=6.9.0'} @@ -2381,6 +2463,48 @@ packages: deprecated: Please use @ensdomains/ens-contracts dev: true + /@envelop/core@5.0.2: + resolution: {integrity: sha512-tVL6OrMe6UjqLosiE+EH9uxh2TQC0469GwF4tE014ugRaDDKKVWwFwZe0TBMlcyHKh5MD4ZxktWo/1hqUxIuhw==} + engines: {node: '>=18.0.0'} + dependencies: + '@envelop/types': 5.0.0 + tslib: 2.6.3 + dev: false + + /@envelop/extended-validation@4.1.0(@envelop/core@5.0.2)(graphql@16.9.0): + resolution: {integrity: sha512-S90LQanW+xg3Lkp2sNiHa2KJnXXpKLucKys05Wk5zpiV0vL0SDX+/cuV+tnDhShWJucunAGi34n8xFCXsUUOkA==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@envelop/core': ^5.0.2 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@envelop/core': 5.0.2 + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + graphql: 16.9.0 + tslib: 2.6.3 + dev: false + + /@envelop/graphql-jit@8.0.3(@envelop/core@5.0.2)(graphql@16.9.0): + resolution: {integrity: sha512-IZnKc7dVOQV9jEi5s5RkG8fVKqc6Ss/mBN9PRt2iYFa9o6XkL/haPLJRfWFsS/CSJfFOQuzLyxYuALA8DaoOYw==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@envelop/core': ^5.0.0 + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@envelop/core': 5.0.2 + graphql: 16.9.0 + graphql-jit: 0.8.6(graphql@16.9.0) + tslib: 2.6.3 + value-or-promise: 1.0.12 + dev: false + + /@envelop/types@5.0.0: + resolution: {integrity: sha512-IPjmgSc4KpQRlO4qbEDnBEixvtb06WDmjKfi/7fkZaryh5HuOmTtixe1EupQI5XfXO8joc3d27uUZ0QdC++euA==} + engines: {node: '>=18.0.0'} + dependencies: + tslib: 2.6.3 + dev: false + /@esbuild/aix-ppc64@0.20.2: resolution: {integrity: sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==} engines: {node: '>=12'} @@ -3178,6 +3302,12 @@ packages: engines: {node: '>=14'} dev: true + /@fastify/merge-json-schemas@0.1.1: + resolution: {integrity: sha512-fERDVz7topgNjtXsJTTW1JKLy0rhuLRcquYqNR9rF7OcVpCa2OVW49ZPDIhaRRCaUuvVxI+N416xUoF76HNSXA==} + dependencies: + fast-deep-equal: 3.1.3 + dev: false + /@float-capital/float-subgraph-uncrashable@0.0.0-internal-testing.5: resolution: {integrity: sha512-yZ0H5e3EpAYKokX/AbtplzlvSxEJY7ZfpvQyDzyODkks0hakAAlDG6fQu1SlDJMWorY7bbq1j7fCiFeTWci6TA==} hasBin: true @@ -3216,6 +3346,138 @@ packages: resolution: {integrity: sha512-XGndio0l5/Gvd6CLIABvsav9HHezgDFFhDfHk1bvLfr9ni8dojqLSvBbotJEjmIwNHL7vK4QzBJTdBRoB+c1ww==} dev: false + /@graphprotocol/client-add-source-name@2.0.7(@graphql-mesh/types@0.102.5)(@graphql-tools/delegate@10.0.21)(@graphql-tools/utils@10.5.4)(@graphql-tools/wrap@10.0.5)(graphql@16.9.0): + resolution: {integrity: sha512-tAEBHwvpjq0bCRDrup8AW6mC8+rMulyrrZXp5xF0Eu924nl4XJOYklpzNp0B8oHs4HI+equHhXlXV6nqQ8jPcg==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@graphql-mesh/types': ^0.78.0 || ^0.79.0 || ^0.80.0 || ^0.81.0 || ^0.82.0 || ^0.83.0 || ^0.84.0 || ^0.85.0 || ^0.89.0 || ^0.90.0 || ^0.91.0 || ^0.93.0 || ^0.94.0 || ^0.97.0 || ^0.98.0 || ^0.99.0 || ^0.100.0 || ^0.101.0 || ^0.102.0 + '@graphql-tools/delegate': ^9.0.32 || ^10.0.0 + '@graphql-tools/utils': ^9.2.1 || ^10.0.0 + '@graphql-tools/wrap': ^9.4.2 || ^10.0.0 + graphql: ^15.2.0 || ^16.0.0 + dependencies: + '@graphql-mesh/types': 0.102.5(@graphql-mesh/store@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-tools/delegate': 10.0.21(graphql@16.9.0) + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + '@graphql-tools/wrap': 10.0.5(graphql@16.9.0) + graphql: 16.9.0 + lodash: 4.17.21 + tslib: 2.6.3 + dev: false + + /@graphprotocol/client-auto-pagination@2.0.7(@graphql-mesh/types@0.102.5)(@graphql-tools/delegate@10.0.21)(@graphql-tools/utils@10.5.4)(@graphql-tools/wrap@10.0.5)(graphql@16.9.0): + resolution: {integrity: sha512-GUvN7taIsOatCPc+kq1hFVk1+I3jIfRrZ5z6s4Nts//uxbZuMmWSHn62FYj/Uq1pG2kTJ/uPZDx2iWH2STZ6BQ==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@graphql-mesh/types': ^0.78.0 || ^0.79.0 || ^0.80.0 || ^0.81.0 || ^0.82.0 || ^0.83.0 || ^0.84.0 || ^0.85.0 || ^0.89.0 || ^0.90.0 || ^0.91.0 || ^0.93.0 || ^0.94.0 || ^0.97.0 || ^0.98.0 || ^0.99.0 || ^0.100.0 || ^0.101.0 || ^0.102.0 + '@graphql-tools/delegate': ^9.0.32 || ^10.0.0 + '@graphql-tools/utils': ^9.2.1 || ^10.0.0 + '@graphql-tools/wrap': ^9.4.2 || ^10.0.0 + graphql: ^15.2.0 || ^16.0.0 + dependencies: + '@graphql-mesh/types': 0.102.5(@graphql-mesh/store@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-tools/delegate': 10.0.21(graphql@16.9.0) + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + '@graphql-tools/wrap': 10.0.5(graphql@16.9.0) + graphql: 16.9.0 + lodash: 4.17.21 + tslib: 2.6.3 + dev: false + + /@graphprotocol/client-auto-type-merging@2.0.7(@graphql-mesh/types@0.102.5)(@graphql-mesh/utils@0.102.5)(@graphql-tools/delegate@10.0.21)(graphql@16.9.0): + resolution: {integrity: sha512-zRQYO85cU/eOwnpcc9gldL3za8gf4xaZrQVwPu/fN2PL/9yPKtkzsVSXPdd4TU+/hoQOOxdP0qvsO3bTljEhxA==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@graphql-mesh/types': ^0.78.0 || ^0.79.0 || ^0.80.0 || ^0.81.0 || ^0.82.0 || ^0.83.0 || ^0.84.0 || ^0.85.0 || ^0.89.0 || ^0.90.0 || ^0.91.0 || ^0.93.0 || ^0.94.0 || ^0.97.0 || ^0.98.0 || ^0.99.0 || ^0.100.0 || ^0.101.0 || ^0.102.0 + '@graphql-tools/delegate': ^9.0.32 || ^10.0.0 + graphql: ^15.2.0 || ^16.0.0 + dependencies: + '@graphql-mesh/transform-type-merging': 0.102.5(@graphql-mesh/types@0.102.5)(@graphql-mesh/utils@0.102.5)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-mesh/types': 0.102.5(@graphql-mesh/store@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-tools/delegate': 10.0.21(graphql@16.9.0) + graphql: 16.9.0 + tslib: 2.6.3 + transitivePeerDependencies: + - '@graphql-mesh/utils' + dev: false + + /@graphprotocol/client-block-tracking@2.0.6(@graphql-mesh/store@0.102.5)(@graphql-tools/delegate@10.0.21)(@types/node@22.0.2)(@types/react@18.3.3)(graphql@16.9.0)(react-dom@18.3.1)(react@18.3.1): + resolution: {integrity: sha512-OStIYKIBIGU1osueFtrzrgK/nXiUsnCr8ql/Medn7k+WRrJpcdY5N74Uxw7J5TTnXqBnJjq9OM3PhIZTjUY6wg==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@graphql-tools/delegate': ^9.0.32 || ^10.0.0 + graphql: ^15.2.0 || ^16.0.0 + dependencies: + '@graphql-mesh/fusion-runtime': 0.8.12(@graphql-mesh/store@0.102.5)(@types/node@22.0.2)(@types/react@18.3.3)(graphql@16.9.0)(react-dom@18.3.1)(react@18.3.1) + '@graphql-tools/delegate': 10.0.21(graphql@16.9.0) + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + graphql: 16.9.0 + tslib: 2.6.3 + transitivePeerDependencies: + - '@graphql-mesh/store' + - '@types/node' + - '@types/react' + - graphql-ws + - react + - react-dom + - subscriptions-transport-ws + dev: false + + /@graphprotocol/client-cli@3.0.7(@envelop/core@5.0.2)(@graphql-mesh/cross-helpers@0.4.6)(@graphql-mesh/store@0.102.5)(@graphql-mesh/types@0.102.5)(@graphql-mesh/utils@0.102.5)(@graphql-tools/delegate@10.0.21)(@graphql-tools/merge@9.0.7)(@graphql-tools/utils@10.5.4)(@graphql-tools/wrap@10.0.5)(@types/node@22.0.2)(@types/react@18.3.3)(graphql-tag@2.12.6)(graphql-yoga@5.7.0)(graphql@16.9.0)(react-dom@18.3.1)(react@18.3.1): + resolution: {integrity: sha512-Y+VRUGV1KOm4gmQyk2kROqvImyWC9o6VHzXxlzSTxAkxh1OsbKBeG8StjnscE/cjlUVJX8CmKkBwI5527pydAA==} + engines: {node: '>=16.0.0'} + hasBin: true + peerDependencies: + graphql: ^15.2.0 || ^16.0.0 + dependencies: + '@graphprotocol/client-add-source-name': 2.0.7(@graphql-mesh/types@0.102.5)(@graphql-tools/delegate@10.0.21)(@graphql-tools/utils@10.5.4)(@graphql-tools/wrap@10.0.5)(graphql@16.9.0) + '@graphprotocol/client-auto-pagination': 2.0.7(@graphql-mesh/types@0.102.5)(@graphql-tools/delegate@10.0.21)(@graphql-tools/utils@10.5.4)(@graphql-tools/wrap@10.0.5)(graphql@16.9.0) + '@graphprotocol/client-auto-type-merging': 2.0.7(@graphql-mesh/types@0.102.5)(@graphql-mesh/utils@0.102.5)(@graphql-tools/delegate@10.0.21)(graphql@16.9.0) + '@graphprotocol/client-block-tracking': 2.0.6(@graphql-mesh/store@0.102.5)(@graphql-tools/delegate@10.0.21)(@types/node@22.0.2)(@types/react@18.3.3)(graphql@16.9.0)(react-dom@18.3.1)(react@18.3.1) + '@graphprotocol/client-polling-live': 2.0.1(@envelop/core@5.0.2)(@graphql-tools/merge@9.0.7)(graphql@16.9.0) + '@graphql-mesh/cli': 0.95.4(graphql-tag@2.12.6)(graphql-yoga@5.7.0)(graphql@16.9.0) + '@graphql-mesh/graphql': 0.102.6(@graphql-mesh/cross-helpers@0.4.6)(@graphql-mesh/store@0.102.5)(@graphql-mesh/types@0.102.5)(@graphql-mesh/utils@0.102.5)(@graphql-tools/utils@10.5.4)(@types/node@22.0.2)(@types/react@18.3.3)(graphql@16.9.0)(react-dom@18.3.1)(react@18.3.1)(tslib@2.6.3) + graphql: 16.9.0 + tslib: 2.6.3 + transitivePeerDependencies: + - '@envelop/core' + - '@graphql-mesh/cross-helpers' + - '@graphql-mesh/store' + - '@graphql-mesh/types' + - '@graphql-mesh/utils' + - '@graphql-tools/delegate' + - '@graphql-tools/merge' + - '@graphql-tools/utils' + - '@graphql-tools/wrap' + - '@types/node' + - '@types/react' + - bufferutil + - encoding + - graphql-tag + - graphql-ws + - graphql-yoga + - react + - react-dom + - subscriptions-transport-ws + - supports-color + - utf-8-validate + dev: false + + /@graphprotocol/client-polling-live@2.0.1(@envelop/core@5.0.2)(@graphql-tools/merge@9.0.7)(graphql@16.9.0): + resolution: {integrity: sha512-jE+9cOM5gAC18uMA7nC7w5X/ru4U4ZrZxWqh3N+gxoLIPpnNYerwzRfFJskPyzl0QQjMiUMua9agqKCyxNBlOA==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@envelop/core': ^2.4.2 || ^3.0.0 || ^4.0.0 || ^5.0.0 + '@graphql-tools/merge': ^8.3.14 || ^9.0.0 + graphql: ^15.2.0 || ^16.0.0 + dependencies: + '@envelop/core': 5.0.2 + '@graphql-tools/merge': 9.0.7(graphql@16.9.0) + '@repeaterjs/repeater': 3.0.6 + graphql: 16.9.0 + tslib: 2.6.3 + dev: false + /@graphprotocol/graph-cli@0.80.1(@types/node@22.0.2)(node-fetch@2.7.0)(typescript@5.5.4): resolution: {integrity: sha512-Kg1o3Ww2B4Q1IhCvYBCJ4fMCv+EqVtLgGvLCZdVyZo4a994Uj76apqkr1KVwRBSW60jgrGkTtpoE2JTNpgbaXg==} engines: {node: '>=18'} @@ -3267,96 +3529,1131 @@ packages: assemblyscript: 0.19.10 dev: false - /@hapi/hoek@9.3.0: - resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==} + /@graphql-codegen/core@4.0.2(graphql@16.9.0): + resolution: {integrity: sha512-IZbpkhwVqgizcjNiaVzNAzm/xbWT6YnGgeOLwVjm4KbJn3V2jchVtuzHH09G5/WkkLSk2wgbXNdwjM41JxO6Eg==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-codegen/plugin-helpers': 5.0.4(graphql@16.9.0) + '@graphql-tools/schema': 10.0.6(graphql@16.9.0) + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + graphql: 16.9.0 + tslib: 2.6.3 dev: false - /@hapi/topo@5.1.0: - resolution: {integrity: sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==} + /@graphql-codegen/plugin-helpers@2.7.2(graphql@16.9.0): + resolution: {integrity: sha512-kln2AZ12uii6U59OQXdjLk5nOlh1pHis1R98cDZGFnfaiAbX9V3fxcZ1MMJkB7qFUymTALzyjZoXXdyVmPMfRg==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 dependencies: - '@hapi/hoek': 9.3.0 + '@graphql-tools/utils': 8.13.1(graphql@16.9.0) + change-case-all: 1.0.14 + common-tags: 1.8.2 + graphql: 16.9.0 + import-from: 4.0.0 + lodash: 4.17.21 + tslib: 2.4.1 dev: false - /@humanwhocodes/config-array@0.11.14: - resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} - engines: {node: '>=10.10.0'} + /@graphql-codegen/plugin-helpers@3.1.2(graphql@16.9.0): + resolution: {integrity: sha512-emOQiHyIliVOIjKVKdsI5MXj312zmRDwmHpyUTZMjfpvxq/UVAHUJIVdVf+lnjjrI+LXBTgMlTWTgHQfmICxjg==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 dependencies: - '@humanwhocodes/object-schema': 2.0.3 - debug: 4.3.4(supports-color@8.1.1) - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - dev: true - - /@humanwhocodes/module-importer@1.0.1: - resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} - engines: {node: '>=12.22'} - dev: true - - /@humanwhocodes/object-schema@2.0.3: - resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} - dev: true + '@graphql-tools/utils': 9.2.1(graphql@16.9.0) + change-case-all: 1.0.15 + common-tags: 1.8.2 + graphql: 16.9.0 + import-from: 4.0.0 + lodash: 4.17.21 + tslib: 2.4.1 + dev: false - /@img/sharp-darwin-arm64@0.33.4: - resolution: {integrity: sha512-p0suNqXufJs9t3RqLBO6vvrgr5OhgbWp76s5gTRvdmxmuv9E1rcaqGUsl3l4mKVmXPkTkTErXediAui4x+8PSA==} - engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} - cpu: [arm64] - os: [darwin] - requiresBuild: true - optionalDependencies: - '@img/sharp-libvips-darwin-arm64': 1.0.2 + /@graphql-codegen/plugin-helpers@5.0.4(graphql@16.9.0): + resolution: {integrity: sha512-MOIuHFNWUnFnqVmiXtrI+4UziMTYrcquljaI5f/T/Bc7oO7sXcfkAvgkNWEEi9xWreYwvuer3VHCuPI/lAFWbw==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + change-case-all: 1.0.15 + common-tags: 1.8.2 + graphql: 16.9.0 + import-from: 4.0.0 + lodash: 4.17.21 + tslib: 2.6.3 dev: false - optional: true - /@img/sharp-darwin-x64@0.33.4: - resolution: {integrity: sha512-0l7yRObwtTi82Z6ebVI2PnHT8EB2NxBgpK2MiKJZJ7cz32R4lxd001ecMhzzsZig3Yv9oclvqqdV93jo9hy+Dw==} - engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} - cpu: [x64] - os: [darwin] - requiresBuild: true - optionalDependencies: - '@img/sharp-libvips-darwin-x64': 1.0.2 + /@graphql-codegen/schema-ast@4.1.0(graphql@16.9.0): + resolution: {integrity: sha512-kZVn0z+th9SvqxfKYgztA6PM7mhnSZaj4fiuBWvMTqA+QqQ9BBed6Pz41KuD/jr0gJtnlr2A4++/0VlpVbCTmQ==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-codegen/plugin-helpers': 5.0.4(graphql@16.9.0) + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + graphql: 16.9.0 + tslib: 2.6.3 dev: false - optional: true - /@img/sharp-libvips-darwin-arm64@1.0.2: - resolution: {integrity: sha512-tcK/41Rq8IKlSaKRCCAuuY3lDJjQnYIW1UXU1kxcEKrfL8WR7N6+rzNoOxoQRJWTAECuKwgAHnPvqXGN8XfkHA==} - engines: {macos: '>=11', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} - cpu: [arm64] - os: [darwin] - requiresBuild: true + /@graphql-codegen/typed-document-node@5.0.9(graphql@16.9.0): + resolution: {integrity: sha512-Wx6fyA4vpfIbfNTMiWUECGnjqzKkJdEbZHxVMIegiCBPzBYPAJV4mZZcildLAfm2FtZcgW4YKtFoTbnbXqPB3w==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-codegen/plugin-helpers': 5.0.4(graphql@16.9.0) + '@graphql-codegen/visitor-plugin-common': 5.3.1(graphql@16.9.0) + auto-bind: 4.0.0 + change-case-all: 1.0.15 + graphql: 16.9.0 + tslib: 2.6.3 + transitivePeerDependencies: + - encoding + - supports-color dev: false - optional: true - /@img/sharp-libvips-darwin-x64@1.0.2: - resolution: {integrity: sha512-Ofw+7oaWa0HiiMiKWqqaZbaYV3/UGL2wAPeLuJTx+9cXpCRdvQhCLG0IH8YGwM0yGWGLpsF4Su9vM1o6aer+Fw==} - engines: {macos: '>=10.13', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} - cpu: [x64] - os: [darwin] - requiresBuild: true + /@graphql-codegen/typescript-generic-sdk@3.1.0(graphql-tag@2.12.6)(graphql@16.9.0): + resolution: {integrity: sha512-nQZi/YGRI1+qCZZsh0V5nz6+hCHSN4OU9tKyOTDsEPyDFnGEukDuRdCH2IZasGn22a3Iu5TUDkgp5w9wEQwGmg==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + graphql-tag: ^2.0.0 + dependencies: + '@graphql-codegen/plugin-helpers': 3.1.2(graphql@16.9.0) + '@graphql-codegen/visitor-plugin-common': 2.13.1(graphql@16.9.0) + auto-bind: 4.0.0 + graphql: 16.9.0 + graphql-tag: 2.12.6(graphql@16.9.0) + tslib: 2.4.1 + transitivePeerDependencies: + - encoding + - supports-color dev: false - optional: true - /@img/sharp-libvips-linux-arm64@1.0.2: - resolution: {integrity: sha512-x7kCt3N00ofFmmkkdshwj3vGPCnmiDh7Gwnd4nUwZln2YjqPxV1NlTyZOvoDWdKQVDL911487HOueBvrpflagw==} - engines: {glibc: '>=2.26', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} - cpu: [arm64] - os: [linux] - requiresBuild: true + /@graphql-codegen/typescript-operations@4.2.3(graphql@16.9.0): + resolution: {integrity: sha512-6z7avSSOr03l5SyKbeDs7MzRyGwnQFSCqQm8Om5wIuoIgXVu2gXRmcJAY/I7SLdAy9xbF4Sho7XNqieFM2CAFQ==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-codegen/plugin-helpers': 5.0.4(graphql@16.9.0) + '@graphql-codegen/typescript': 4.0.9(graphql@16.9.0) + '@graphql-codegen/visitor-plugin-common': 5.3.1(graphql@16.9.0) + auto-bind: 4.0.0 + graphql: 16.9.0 + tslib: 2.6.3 + transitivePeerDependencies: + - encoding + - supports-color dev: false - optional: true - /@img/sharp-libvips-linux-arm@1.0.2: - resolution: {integrity: sha512-iLWCvrKgeFoglQxdEwzu1eQV04o8YeYGFXtfWU26Zr2wWT3q3MTzC+QTCO3ZQfWd3doKHT4Pm2kRmLbupT+sZw==} - engines: {glibc: '>=2.28', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} - cpu: [arm] - os: [linux] - requiresBuild: true + /@graphql-codegen/typescript-resolvers@4.2.1(graphql@16.9.0): + resolution: {integrity: sha512-q/ggqNSKNGG9bn49DdZrw2KokagDZmzl1EpxIfzmpHrPa3XaCLfxQuNNEUhqEXtJzQZtLfuYvGy1y+MrTU8WnA==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-codegen/plugin-helpers': 5.0.4(graphql@16.9.0) + '@graphql-codegen/typescript': 4.0.9(graphql@16.9.0) + '@graphql-codegen/visitor-plugin-common': 5.3.1(graphql@16.9.0) + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + auto-bind: 4.0.0 + graphql: 16.9.0 + tslib: 2.6.3 + transitivePeerDependencies: + - encoding + - supports-color dev: false - optional: true - /@img/sharp-libvips-linux-s390x@1.0.2: - resolution: {integrity: sha512-cmhQ1J4qVhfmS6szYW7RT+gLJq9dH2i4maq+qyXayUSn9/3iY2ZeWpbAgSpSVbV2E1JUL2Gg7pwnYQ1h8rQIog==} + /@graphql-codegen/typescript@4.0.9(graphql@16.9.0): + resolution: {integrity: sha512-0O35DMR4d/ctuHL1Zo6mRUUzp0BoszKfeWsa6sCm/g70+S98+hEfTwZNDkQHylLxapiyjssF9uw/F+sXqejqLw==} + peerDependencies: + graphql: ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-codegen/plugin-helpers': 5.0.4(graphql@16.9.0) + '@graphql-codegen/schema-ast': 4.1.0(graphql@16.9.0) + '@graphql-codegen/visitor-plugin-common': 5.3.1(graphql@16.9.0) + auto-bind: 4.0.0 + graphql: 16.9.0 + tslib: 2.6.3 + transitivePeerDependencies: + - encoding + - supports-color + dev: false + + /@graphql-codegen/visitor-plugin-common@2.13.1(graphql@16.9.0): + resolution: {integrity: sha512-mD9ufZhDGhyrSaWQGrU1Q1c5f01TeWtSWy/cDwXYjJcHIj1Y/DG2x0tOflEfCvh5WcnmHNIw4lzDsg1W7iFJEg==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-codegen/plugin-helpers': 2.7.2(graphql@16.9.0) + '@graphql-tools/optimize': 1.4.0(graphql@16.9.0) + '@graphql-tools/relay-operation-optimizer': 6.5.18(graphql@16.9.0) + '@graphql-tools/utils': 8.13.1(graphql@16.9.0) + auto-bind: 4.0.0 + change-case-all: 1.0.14 + dependency-graph: 0.11.0 + graphql: 16.9.0 + graphql-tag: 2.12.6(graphql@16.9.0) + parse-filepath: 1.0.2 + tslib: 2.4.1 + transitivePeerDependencies: + - encoding + - supports-color + dev: false + + /@graphql-codegen/visitor-plugin-common@5.3.1(graphql@16.9.0): + resolution: {integrity: sha512-MktoBdNZhSmugiDjmFl1z6rEUUaqyxtFJYWnDilE7onkPgyw//O0M+TuPBJPBWdyV6J2ond0Hdqtq+rkghgSIQ==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + '@graphql-codegen/plugin-helpers': 5.0.4(graphql@16.9.0) + '@graphql-tools/optimize': 2.0.0(graphql@16.9.0) + '@graphql-tools/relay-operation-optimizer': 7.0.1(graphql@16.9.0) + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + auto-bind: 4.0.0 + change-case-all: 1.0.15 + dependency-graph: 0.11.0 + graphql: 16.9.0 + graphql-tag: 2.12.6(graphql@16.9.0) + parse-filepath: 1.0.2 + tslib: 2.6.3 + transitivePeerDependencies: + - encoding + - supports-color + dev: false + + /@graphql-inspector/core@6.1.0(graphql@16.9.0): + resolution: {integrity: sha512-5/kqD5330duUsfMBfhMc0iVld76JwSKTkKi7aOr1x9MvSnP8p1anQo7BCNZ5VY9+EvWn4njHbkNfdS/lrqsi+A==} + engines: {node: '>=18.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + dependency-graph: 1.0.0 + graphql: 16.9.0 + object-inspect: 1.13.1 + tslib: 2.6.2 + dev: false + + /@graphql-mesh/cache-localforage@0.102.5(@graphql-mesh/types@0.102.5)(@graphql-mesh/utils@0.102.5)(graphql@16.9.0)(tslib@2.6.3): + resolution: {integrity: sha512-VL8RRAR6ccpy83GQpT8kFW0G+DDC3efzaVu/XmqvtHYiUflC+CGDm6K9svPgHcsadcQ1mVLbByEGoLSoOq8UXw==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@graphql-mesh/types': ^0.102.5 + '@graphql-mesh/utils': ^0.102.5 + graphql: '*' + tslib: ^2.4.0 + dependencies: + '@graphql-mesh/types': 0.102.5(@graphql-mesh/store@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-mesh/utils': 0.102.5(@graphql-mesh/cross-helpers@0.4.6)(@graphql-mesh/types@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3) + graphql: 16.9.0 + localforage: 1.10.0 + tslib: 2.6.3 + dev: false + + /@graphql-mesh/cli@0.95.4(graphql-tag@2.12.6)(graphql-yoga@5.7.0)(graphql@16.9.0): + resolution: {integrity: sha512-NVVOQaszhR1aQCWR3oxuuMZvgyZMW+Zyd53GO8CA15RhPGcPVqaL/zz5cGXSKjIZ6HK0VThGuxzocsfq0AcsOw==} + engines: {node: '>=16.0.0'} + hasBin: true + peerDependencies: + graphql: '*' + dependencies: + '@graphql-codegen/core': 4.0.2(graphql@16.9.0) + '@graphql-codegen/typed-document-node': 5.0.9(graphql@16.9.0) + '@graphql-codegen/typescript': 4.0.9(graphql@16.9.0) + '@graphql-codegen/typescript-generic-sdk': 3.1.0(graphql-tag@2.12.6)(graphql@16.9.0) + '@graphql-codegen/typescript-operations': 4.2.3(graphql@16.9.0) + '@graphql-codegen/typescript-resolvers': 4.2.1(graphql@16.9.0) + '@graphql-mesh/config': 0.104.6(@graphql-mesh/cross-helpers@0.4.6)(@graphql-mesh/runtime@0.103.6)(@graphql-mesh/store@0.102.5)(@graphql-mesh/types@0.102.5)(@graphql-mesh/utils@0.102.5)(@graphql-tools/utils@10.5.4)(graphql-yoga@5.7.0)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-mesh/cross-helpers': 0.4.6(@graphql-tools/utils@10.5.4)(graphql@16.9.0) + '@graphql-mesh/http': 0.103.6(@graphql-mesh/cross-helpers@0.4.6)(@graphql-mesh/runtime@0.103.6)(@graphql-mesh/types@0.102.5)(@graphql-mesh/utils@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-mesh/include': 0.1.0 + '@graphql-mesh/runtime': 0.103.6(@graphql-mesh/cross-helpers@0.4.6)(@graphql-mesh/types@0.102.5)(@graphql-mesh/utils@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-mesh/store': 0.102.5(@graphql-mesh/cross-helpers@0.4.6)(@graphql-mesh/types@0.102.5)(@graphql-mesh/utils@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-mesh/types': 0.102.5(@graphql-mesh/store@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-mesh/utils': 0.102.5(@graphql-mesh/cross-helpers@0.4.6)(@graphql-mesh/types@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + ajv: 8.13.0 + change-case: 4.1.2 + cosmiconfig: 9.0.0(typescript@5.5.4) + dotenv: 16.4.5 + graphql: 16.9.0 + graphql-import-node: 0.0.5(graphql@16.9.0) + graphql-ws: 5.16.0(graphql@16.9.0) + json-bigint-patch: 0.0.8 + json5: 2.2.3 + mkdirp: 3.0.1 + open: 7.4.2 + pascal-case: 3.1.2 + rimraf: 6.0.1 + tslib: 2.6.3 + typescript: 5.5.4 + ws: 8.18.0 + yargs: 17.7.2 + optionalDependencies: + node-libcurl: 4.0.0 + uWebSockets.js: github.com/uNetworking/uWebSockets.js/442087c0a01bf146acb7386910739ec81df06700 + transitivePeerDependencies: + - bufferutil + - encoding + - graphql-tag + - graphql-yoga + - supports-color + - utf-8-validate + dev: false + + /@graphql-mesh/config@0.104.6(@graphql-mesh/cross-helpers@0.4.6)(@graphql-mesh/runtime@0.103.6)(@graphql-mesh/store@0.102.5)(@graphql-mesh/types@0.102.5)(@graphql-mesh/utils@0.102.5)(@graphql-tools/utils@10.5.4)(graphql-yoga@5.7.0)(graphql@16.9.0)(tslib@2.6.3): + resolution: {integrity: sha512-pbz+XkK9W9b4mln+VuZt3JbqHpKzGSWBeI95E5y4sUCqRvY2t+61dyxTMtJmSDKkYLMM9gn6tXQVmbJzG5uSvw==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@graphql-mesh/cross-helpers': ^0.4.6 + '@graphql-mesh/runtime': ^0.103.6 + '@graphql-mesh/store': ^0.102.5 + '@graphql-mesh/types': ^0.102.5 + '@graphql-mesh/utils': ^0.102.5 + '@graphql-tools/utils': ^10.5.3 + graphql: '*' + tslib: ^2.4.0 + dependencies: + '@envelop/core': 5.0.2 + '@graphql-mesh/cache-localforage': 0.102.5(@graphql-mesh/types@0.102.5)(@graphql-mesh/utils@0.102.5)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-mesh/cross-helpers': 0.4.6(@graphql-tools/utils@10.5.4)(graphql@16.9.0) + '@graphql-mesh/merger-bare': 0.102.5(@graphql-mesh/store@0.102.5)(@graphql-mesh/types@0.102.5)(@graphql-mesh/utils@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-mesh/merger-stitching': 0.102.5(@graphql-mesh/store@0.102.5)(@graphql-mesh/types@0.102.5)(@graphql-mesh/utils@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-mesh/runtime': 0.103.6(@graphql-mesh/cross-helpers@0.4.6)(@graphql-mesh/types@0.102.5)(@graphql-mesh/utils@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-mesh/store': 0.102.5(@graphql-mesh/cross-helpers@0.4.6)(@graphql-mesh/types@0.102.5)(@graphql-mesh/utils@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-mesh/types': 0.102.5(@graphql-mesh/store@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-mesh/utils': 0.102.5(@graphql-mesh/cross-helpers@0.4.6)(@graphql-mesh/types@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-tools/code-file-loader': 8.1.3(graphql@16.9.0) + '@graphql-tools/graphql-file-loader': 8.0.1(graphql@16.9.0) + '@graphql-tools/load': 8.0.2(graphql@16.9.0) + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + '@graphql-yoga/plugin-persisted-operations': 3.7.0(@graphql-tools/utils@10.5.4)(graphql-yoga@5.7.0)(graphql@16.9.0) + '@whatwg-node/fetch': 0.9.21 + camel-case: 4.1.2 + graphql: 16.9.0 + param-case: 3.0.4 + pascal-case: 3.1.2 + tslib: 2.6.3 + transitivePeerDependencies: + - graphql-yoga + - supports-color + dev: false + + /@graphql-mesh/cross-helpers@0.4.6(@graphql-tools/utils@10.5.4)(graphql@16.9.0): + resolution: {integrity: sha512-jCwVoZ/90vGsqafBk6NlgzIwQime7y1PpDjY/cnoqITjF8+znviff+gc70Oqgjget+wF7vrvWveWu7KeB9gddg==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@graphql-tools/utils': ^10.5.3 + graphql: '*' + dependencies: + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + graphql: 16.9.0 + path-browserify: 1.0.1 + dev: false + + /@graphql-mesh/fusion-runtime@0.8.12(@graphql-mesh/store@0.102.5)(@types/node@22.0.2)(@types/react@18.3.3)(graphql@16.9.0)(react-dom@18.3.1)(react@18.3.1): + resolution: {integrity: sha512-9Q+tjghR2hDQFagZ/Kk6q9Lj1A0klMVnm9MvtIy4n8gFJCAsGL4ftSrXrBmZVh++DkZ/zm4C/riyzzSXKXD90w==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@envelop/core': 5.0.2 + '@graphql-mesh/cross-helpers': 0.4.6(@graphql-tools/utils@10.5.4)(graphql@16.9.0) + '@graphql-mesh/runtime': 0.103.6(@graphql-mesh/cross-helpers@0.4.6)(@graphql-mesh/types@0.102.5)(@graphql-mesh/utils@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-mesh/transport-common': 0.7.6(@graphql-mesh/types@0.102.5)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-mesh/types': 0.102.5(@graphql-mesh/store@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-mesh/utils': 0.102.5(@graphql-mesh/cross-helpers@0.4.6)(@graphql-mesh/types@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-tools/delegate': 10.0.21(graphql@16.9.0) + '@graphql-tools/executor': 1.3.1(graphql@16.9.0) + '@graphql-tools/federation': 2.2.10(@types/node@22.0.2)(@types/react@18.3.3)(graphql@16.9.0)(react-dom@18.3.1)(react@18.3.1) + '@graphql-tools/stitch': 9.2.10(graphql@16.9.0) + '@graphql-tools/stitching-directives': 3.1.2(graphql@16.9.0) + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + '@graphql-tools/wrap': 10.0.5(graphql@16.9.0) + '@whatwg-node/disposablestack': 0.0.5 + change-case: 4.1.2 + graphql: 16.9.0 + graphql-yoga: 5.7.0(graphql@16.9.0) + tslib: 2.6.3 + transitivePeerDependencies: + - '@graphql-mesh/store' + - '@types/node' + - '@types/react' + - graphql-ws + - react + - react-dom + - subscriptions-transport-ws + dev: false + + /@graphql-mesh/graphql@0.102.6(@graphql-mesh/cross-helpers@0.4.6)(@graphql-mesh/store@0.102.5)(@graphql-mesh/types@0.102.5)(@graphql-mesh/utils@0.102.5)(@graphql-tools/utils@10.5.4)(@types/node@22.0.2)(@types/react@18.3.3)(graphql@16.9.0)(react-dom@18.3.1)(react@18.3.1)(tslib@2.6.3): + resolution: {integrity: sha512-KrwU+QwxC9qFo6CpJr7m2/GCEnyZyMB+ioiINqMftglQvk70i3JPNSDYP+73H2sQNwWKke89lBP2jRYakduRzA==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@graphql-mesh/cross-helpers': ^0.4.6 + '@graphql-mesh/store': ^0.102.5 + '@graphql-mesh/types': ^0.102.5 + '@graphql-mesh/utils': ^0.102.5 + '@graphql-tools/utils': ^10.5.3 + graphql: '*' + tslib: ^2.4.0 + dependencies: + '@graphql-mesh/cross-helpers': 0.4.6(@graphql-tools/utils@10.5.4)(graphql@16.9.0) + '@graphql-mesh/store': 0.102.5(@graphql-mesh/cross-helpers@0.4.6)(@graphql-mesh/types@0.102.5)(@graphql-mesh/utils@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-mesh/string-interpolation': 0.5.6(graphql@16.9.0)(tslib@2.6.3) + '@graphql-mesh/types': 0.102.5(@graphql-mesh/store@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-mesh/utils': 0.102.5(@graphql-mesh/cross-helpers@0.4.6)(@graphql-mesh/types@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-tools/delegate': 10.0.21(graphql@16.9.0) + '@graphql-tools/federation': 2.2.10(@types/node@22.0.2)(@types/react@18.3.3)(graphql@16.9.0)(react-dom@18.3.1)(react@18.3.1) + '@graphql-tools/url-loader': 8.0.2(@types/node@22.0.2)(graphql@16.9.0) + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + graphql: 16.9.0 + lodash.get: 4.4.2 + tslib: 2.6.3 + transitivePeerDependencies: + - '@types/node' + - '@types/react' + - bufferutil + - encoding + - graphql-ws + - react + - react-dom + - subscriptions-transport-ws + - utf-8-validate + dev: false + + /@graphql-mesh/http@0.103.6(@graphql-mesh/cross-helpers@0.4.6)(@graphql-mesh/runtime@0.103.6)(@graphql-mesh/types@0.102.5)(@graphql-mesh/utils@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3): + resolution: {integrity: sha512-Qcpb4J7mIi84/pFMdLQMu5TZ1A70xDasnofG3UikxbYi8rIPpBGSjt7a6eBxy/hfahvn57AN9e8QsT1TL+IWXA==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@graphql-mesh/cross-helpers': ^0.4.6 + '@graphql-mesh/runtime': ^0.103.6 + '@graphql-mesh/types': ^0.102.5 + '@graphql-mesh/utils': ^0.102.5 + '@graphql-tools/utils': ^10.5.3 + graphql: '*' + tslib: ^2.4.0 + dependencies: + '@graphql-mesh/cross-helpers': 0.4.6(@graphql-tools/utils@10.5.4)(graphql@16.9.0) + '@graphql-mesh/runtime': 0.103.6(@graphql-mesh/cross-helpers@0.4.6)(@graphql-mesh/types@0.102.5)(@graphql-mesh/utils@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-mesh/types': 0.102.5(@graphql-mesh/store@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-mesh/utils': 0.102.5(@graphql-mesh/cross-helpers@0.4.6)(@graphql-mesh/types@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + '@whatwg-node/server': 0.9.49 + graphql: 16.9.0 + graphql-yoga: 5.7.0(graphql@16.9.0) + tslib: 2.6.3 + dev: false + + /@graphql-mesh/include@0.1.0: + resolution: {integrity: sha512-CtuhmzwT4BRq2YoCW6RWESumcBn9ZTDj/loyf2HbwT9y2i4g7Rs5bvcfsFUb2MB3gCa9k+C9vv1Q9klH4fxGKQ==} + engines: {node: '>=16.0.0'} + dependencies: + dotenv: 16.4.5 + get-tsconfig: 4.7.6 + jiti: 1.21.6 + dev: false + + /@graphql-mesh/merger-bare@0.102.5(@graphql-mesh/store@0.102.5)(@graphql-mesh/types@0.102.5)(@graphql-mesh/utils@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3): + resolution: {integrity: sha512-8VJNzYnn587wU4+HwaKJGUjWVl0SxaPRgQw0Hs2cR8Ns23/TbmSivMlHh1Jafeh5Io8j6IT3Yh5Uih9zNXT+Hw==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@graphql-mesh/types': ^0.102.5 + '@graphql-mesh/utils': ^0.102.5 + '@graphql-tools/utils': ^10.5.3 + graphql: '*' + tslib: ^2.4.0 + dependencies: + '@graphql-mesh/merger-stitching': 0.102.5(@graphql-mesh/store@0.102.5)(@graphql-mesh/types@0.102.5)(@graphql-mesh/utils@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-mesh/types': 0.102.5(@graphql-mesh/store@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-mesh/utils': 0.102.5(@graphql-mesh/cross-helpers@0.4.6)(@graphql-mesh/types@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-tools/schema': 10.0.6(graphql@16.9.0) + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + graphql: 16.9.0 + tslib: 2.6.3 + transitivePeerDependencies: + - '@graphql-mesh/store' + dev: false + + /@graphql-mesh/merger-stitching@0.102.5(@graphql-mesh/store@0.102.5)(@graphql-mesh/types@0.102.5)(@graphql-mesh/utils@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3): + resolution: {integrity: sha512-qtT2PgUMhzsiRV2yhW7b7CfiX9V4aECTjjzgTuxEihnSpKUFsG53IKBfHvr88L7CLzJghRo0JJezZgJspG550A==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@graphql-mesh/store': ^0.102.5 + '@graphql-mesh/types': ^0.102.5 + '@graphql-mesh/utils': ^0.102.5 + '@graphql-tools/utils': ^10.5.3 + graphql: '*' + tslib: ^2.4.0 + dependencies: + '@graphql-mesh/store': 0.102.5(@graphql-mesh/cross-helpers@0.4.6)(@graphql-mesh/types@0.102.5)(@graphql-mesh/utils@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-mesh/types': 0.102.5(@graphql-mesh/store@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-mesh/utils': 0.102.5(@graphql-mesh/cross-helpers@0.4.6)(@graphql-mesh/types@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-tools/delegate': 10.0.21(graphql@16.9.0) + '@graphql-tools/schema': 10.0.6(graphql@16.9.0) + '@graphql-tools/stitch': 9.2.10(graphql@16.9.0) + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + graphql: 16.9.0 + tslib: 2.6.3 + dev: false + + /@graphql-mesh/runtime@0.103.6(@graphql-mesh/cross-helpers@0.4.6)(@graphql-mesh/types@0.102.5)(@graphql-mesh/utils@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3): + resolution: {integrity: sha512-mTqyqKWeHF7b/ZFyyc0lHUqYkCXaNUugtp66pgp1lg5fvqn/2B7GPYteeVCCerJD2kpqLp0R3Zpb3Atb/8Fifg==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@graphql-mesh/cross-helpers': ^0.4.6 + '@graphql-mesh/types': ^0.102.5 + '@graphql-mesh/utils': ^0.102.5 + '@graphql-tools/utils': ^10.5.3 + graphql: '*' + tslib: ^2.4.0 + dependencies: + '@envelop/core': 5.0.2 + '@envelop/extended-validation': 4.1.0(@envelop/core@5.0.2)(graphql@16.9.0) + '@envelop/graphql-jit': 8.0.3(@envelop/core@5.0.2)(graphql@16.9.0) + '@graphql-mesh/cross-helpers': 0.4.6(@graphql-tools/utils@10.5.4)(graphql@16.9.0) + '@graphql-mesh/string-interpolation': 0.5.6(graphql@16.9.0)(tslib@2.6.3) + '@graphql-mesh/types': 0.102.5(@graphql-mesh/store@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-mesh/utils': 0.102.5(@graphql-mesh/cross-helpers@0.4.6)(@graphql-mesh/types@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-tools/batch-delegate': 9.0.3(graphql@16.9.0) + '@graphql-tools/delegate': 10.0.21(graphql@16.9.0) + '@graphql-tools/executor': 1.3.1(graphql@16.9.0) + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + '@graphql-tools/wrap': 10.0.5(graphql@16.9.0) + '@whatwg-node/fetch': 0.9.21 + graphql: 16.9.0 + graphql-jit: 0.8.6(graphql@16.9.0) + tslib: 2.6.3 + dev: false + + /@graphql-mesh/store@0.102.5(@graphql-mesh/cross-helpers@0.4.6)(@graphql-mesh/types@0.102.5)(@graphql-mesh/utils@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3): + resolution: {integrity: sha512-szzwC9UdKM4MT0wu0c0qoHkCKI3b/Yr8/G64wL+bFa61b0WC0I6VOCePiVYHrE1ORTRCF6LyaUkh9d0ZC2qr+g==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@graphql-mesh/cross-helpers': ^0.4.6 + '@graphql-mesh/types': ^0.102.5 + '@graphql-mesh/utils': ^0.102.5 + '@graphql-tools/utils': ^10.5.3 + graphql: '*' + tslib: ^2.4.0 + dependencies: + '@graphql-inspector/core': 6.1.0(graphql@16.9.0) + '@graphql-mesh/cross-helpers': 0.4.6(@graphql-tools/utils@10.5.4)(graphql@16.9.0) + '@graphql-mesh/types': 0.102.5(@graphql-mesh/store@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-mesh/utils': 0.102.5(@graphql-mesh/cross-helpers@0.4.6)(@graphql-mesh/types@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + graphql: 16.9.0 + tslib: 2.6.3 + dev: false + + /@graphql-mesh/string-interpolation@0.5.6(graphql@16.9.0)(tslib@2.6.3): + resolution: {integrity: sha512-zcBCc68lzNAqiccVhq/lCVtAQi6zHiyu0VdIPdfq48P7wd95J9nBqdJI21caOVKiR5giDpRQL/uMFMzRoQYkRA==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: '*' + tslib: ^2.4.0 + dependencies: + dayjs: 1.11.13 + graphql: 16.9.0 + json-pointer: 0.6.2 + lodash.get: 4.4.2 + tslib: 2.6.3 + dev: false + + /@graphql-mesh/transform-type-merging@0.102.5(@graphql-mesh/types@0.102.5)(@graphql-mesh/utils@0.102.5)(graphql@16.9.0)(tslib@2.6.3): + resolution: {integrity: sha512-cgp8GdS00zEloEM9iB/+e3Ju/WUHMd5k3u9MYYyKKOqeaMZanGaPJcgxF5SvoFfTB+LmMLoEqJAHx94fS7yrYQ==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@graphql-mesh/types': ^0.102.5 + '@graphql-mesh/utils': ^0.102.5 + graphql: '*' + tslib: ^2.4.0 + dependencies: + '@graphql-mesh/types': 0.102.5(@graphql-mesh/store@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-mesh/utils': 0.102.5(@graphql-mesh/cross-helpers@0.4.6)(@graphql-mesh/types@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-tools/delegate': 10.0.21(graphql@16.9.0) + '@graphql-tools/stitching-directives': 3.1.2(graphql@16.9.0) + graphql: 16.9.0 + tslib: 2.6.3 + dev: false + + /@graphql-mesh/transport-common@0.7.6(@graphql-mesh/types@0.102.5)(graphql@16.9.0)(tslib@2.6.3): + resolution: {integrity: sha512-flhu4bxwWhO6awj0bDCqBtDQVGG+AcIsAhO5MHFGOviwKG4sSqNUiK4O0YoEJ6oNbs26MCPea+DwWXhSQ5EVRA==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@graphql-mesh/types': ^0.102.5 + graphql: '*' + tslib: ^2.4.0 + dependencies: + '@envelop/core': 5.0.2 + '@graphql-mesh/types': 0.102.5(@graphql-mesh/store@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-tools/delegate': 10.0.21(graphql@16.9.0) + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + graphql: 16.9.0 + tslib: 2.6.3 + dev: false + + /@graphql-mesh/types@0.102.5(@graphql-mesh/store@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3): + resolution: {integrity: sha512-bFcPZQVrNF4+QLk+O3IqXASsl0mNtss18aD0UzaDLI5ai5MkS7vXO222oGUcxC1sGc8poyZJwL/nlIYnv4HoPA==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@graphql-mesh/store': ^0.102.5 + '@graphql-tools/utils': ^10.5.3 + graphql: '*' + tslib: ^2.4.0 + dependencies: + '@graphql-mesh/store': 0.102.5(@graphql-mesh/cross-helpers@0.4.6)(@graphql-mesh/types@0.102.5)(@graphql-mesh/utils@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-tools/batch-delegate': 9.0.3(graphql@16.9.0) + '@graphql-tools/delegate': 10.0.21(graphql@16.9.0) + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + '@graphql-typed-document-node/core': 3.2.0(graphql@16.9.0) + graphql: 16.9.0 + tslib: 2.6.3 + dev: false + + /@graphql-mesh/utils@0.102.5(@graphql-mesh/cross-helpers@0.4.6)(@graphql-mesh/types@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3): + resolution: {integrity: sha512-7rAFz7Y2/gzPmWNMc1vloiS5KJ+MhlxMuweu4/htCBmHARv04pBzAcRW3TfV3sSuqM/3g2C08xNEXQn9+TlMmQ==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@graphql-mesh/cross-helpers': ^0.4.6 + '@graphql-mesh/types': ^0.102.5 + '@graphql-tools/utils': ^10.5.3 + graphql: '*' + tslib: ^2.4.0 + dependencies: + '@graphql-mesh/cross-helpers': 0.4.6(@graphql-tools/utils@10.5.4)(graphql@16.9.0) + '@graphql-mesh/string-interpolation': 0.5.6(graphql@16.9.0)(tslib@2.6.3) + '@graphql-mesh/types': 0.102.5(@graphql-mesh/store@0.102.5)(@graphql-tools/utils@10.5.4)(graphql@16.9.0)(tslib@2.6.3) + '@graphql-tools/delegate': 10.0.21(graphql@16.9.0) + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + '@whatwg-node/disposablestack': 0.0.5 + '@whatwg-node/fetch': 0.9.21 + dset: 3.1.4 + graphql: 16.9.0 + js-yaml: 4.1.0 + lodash.get: 4.4.2 + lodash.topath: 4.5.2 + tiny-lru: 11.2.11 + tslib: 2.6.3 + dev: false + + /@graphql-tools/batch-delegate@9.0.3(graphql@16.9.0): + resolution: {integrity: sha512-wYYbDLQeXU+lEUQJDjylN/e1V3OTVkeJSZYgroDniBfg3etDuOJruAIWZ6S6skKB1PZBy1emEbs6HjrziHeX0A==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/delegate': 10.0.21(graphql@16.9.0) + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + dataloader: 2.2.2 + graphql: 16.9.0 + tslib: 2.6.3 + value-or-promise: 1.0.12 + dev: false + + /@graphql-tools/batch-execute@9.0.4(graphql@16.9.0): + resolution: {integrity: sha512-kkebDLXgDrep5Y0gK1RN3DMUlLqNhg60OAz0lTCqrYeja6DshxLtLkj+zV4mVbBA4mQOEoBmw6g1LZs3dA84/w==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + dataloader: 2.2.2 + graphql: 16.9.0 + tslib: 2.6.3 + value-or-promise: 1.0.12 + dev: false + + /@graphql-tools/code-file-loader@8.1.3(graphql@16.9.0): + resolution: {integrity: sha512-Qoo8VyU0ux7k20DkzL5wFm7Y6iqlG1GQ0xA4T3EQbm4B/qbENsMc38l76QnXYIVmIlKAnD9EAvzxPEQ8iv+ZPA==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/graphql-tag-pluck': 8.3.2(graphql@16.9.0) + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + globby: 11.1.0 + graphql: 16.9.0 + tslib: 2.6.3 + unixify: 1.0.0 + transitivePeerDependencies: + - supports-color + dev: false + + /@graphql-tools/delegate@10.0.21(graphql@16.9.0): + resolution: {integrity: sha512-UytyYVvDfLQbCYG1aQo8Vc67c1WhEjzW9ytYKEEqMJSdlwfMCujHmCz7EyH5DNjTAKapDHuQcN5VivKGap/Beg==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/batch-execute': 9.0.4(graphql@16.9.0) + '@graphql-tools/executor': 1.3.1(graphql@16.9.0) + '@graphql-tools/schema': 10.0.6(graphql@16.9.0) + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + '@repeaterjs/repeater': 3.0.6 + dataloader: 2.2.2 + graphql: 16.9.0 + tslib: 2.6.3 + dev: false + + /@graphql-tools/executor-graphql-ws@1.2.0(graphql@16.9.0): + resolution: {integrity: sha512-tSYC1QdrabWexLrYV0UI3uRGbde9WCY/bRhq6Jc+VXMZcfq6ea6pP5NEAVTfwbhUQ4xZvJABVVbKXtKb9uTg1w==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + '@types/ws': 8.5.12 + graphql: 16.9.0 + graphql-ws: 5.16.0(graphql@16.9.0) + isomorphic-ws: 5.0.0(ws@8.18.0) + tslib: 2.6.3 + ws: 8.18.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: false + + /@graphql-tools/executor-http@1.1.6(@types/node@22.0.2)(graphql@16.9.0): + resolution: {integrity: sha512-wGKjJzbi6em8cWI3sry6T7kAgoxMXYNM+KlbsWczPvIsHvv1cqXlrP1lwC6f7Ja1FfWdU1ZIEgOv93ext7IDyQ==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + '@repeaterjs/repeater': 3.0.6 + '@whatwg-node/fetch': 0.9.21 + extract-files: 11.0.0 + graphql: 16.9.0 + meros: 1.3.0(@types/node@22.0.2) + tslib: 2.6.3 + value-or-promise: 1.0.12 + transitivePeerDependencies: + - '@types/node' + dev: false + + /@graphql-tools/executor-legacy-ws@1.1.0(graphql@16.9.0): + resolution: {integrity: sha512-k+6ZyiaAd8SmwuzbEOfA/LVkuI1nqidhoMw+CJ7c41QGOjSMzc0VS0UZbJyeitI0n7a+uP/Meln1wjzJ2ReDtQ==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + '@types/ws': 8.5.12 + graphql: 16.9.0 + isomorphic-ws: 5.0.0(ws@8.18.0) + tslib: 2.6.3 + ws: 8.18.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: false + + /@graphql-tools/executor@1.3.1(graphql@16.9.0): + resolution: {integrity: sha512-tgJDdGf9SCAm64ofEMZdv925u6/J+eTmv36TGNLxgP2DpCJsZ6gnJ4A+0D28EazDXqJIvMiPd+3d+o3cCRCAnQ==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + '@graphql-typed-document-node/core': 3.2.0(graphql@16.9.0) + '@repeaterjs/repeater': 3.0.6 + graphql: 16.9.0 + tslib: 2.6.3 + value-or-promise: 1.0.12 + dev: false + + /@graphql-tools/federation@2.2.10(@types/node@22.0.2)(@types/react@18.3.3)(graphql@16.9.0)(react-dom@18.3.1)(react@18.3.1): + resolution: {integrity: sha512-MF7/TUl+v+dzb8+mutVvivB4sAOmKHK+mJc0TZoM0rCpYNJAIxjp8NIg64z8jImjEPCRmPpxI4uH0kFH3ErWMQ==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/delegate': 10.0.21(graphql@16.9.0) + '@graphql-tools/executor-http': 1.1.6(@types/node@22.0.2)(graphql@16.9.0) + '@graphql-tools/merge': 9.0.7(graphql@16.9.0) + '@graphql-tools/schema': 10.0.6(graphql@16.9.0) + '@graphql-tools/stitch': 9.2.10(graphql@16.9.0) + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + '@graphql-tools/wrap': 10.0.5(graphql@16.9.0) + '@whatwg-node/fetch': 0.9.21 + graphql: 16.9.0 + tslib: 2.6.3 + value-or-promise: 1.0.12 + optionalDependencies: + '@apollo/client': 3.11.8(@types/react@18.3.3)(graphql@16.9.0)(react-dom@18.3.1)(react@18.3.1) + transitivePeerDependencies: + - '@types/node' + - '@types/react' + - graphql-ws + - react + - react-dom + - subscriptions-transport-ws + dev: false + + /@graphql-tools/graphql-file-loader@8.0.1(graphql@16.9.0): + resolution: {integrity: sha512-7gswMqWBabTSmqbaNyWSmRRpStWlcCkBc73E6NZNlh4YNuiyKOwbvSkOUYFOqFMfEL+cFsXgAvr87Vz4XrYSbA==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/import': 7.0.1(graphql@16.9.0) + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + globby: 11.1.0 + graphql: 16.9.0 + tslib: 2.6.3 + unixify: 1.0.0 + dev: false + + /@graphql-tools/graphql-tag-pluck@8.3.2(graphql@16.9.0): + resolution: {integrity: sha512-wJKkDjXRg2qJAVhAVE96zJGMli8Ity9mKUB7gTbvJwsAniaquRqLcTXUQ19X9qVT4ACzbbp+tAfk96b2U3tfog==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@babel/core': 7.25.2 + '@babel/parser': 7.25.3 + '@babel/plugin-syntax-import-assertions': 7.24.7(@babel/core@7.25.2) + '@babel/traverse': 7.25.3 + '@babel/types': 7.25.2 + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + graphql: 16.9.0 + tslib: 2.6.3 + transitivePeerDependencies: + - supports-color + dev: false + + /@graphql-tools/import@7.0.1(graphql@16.9.0): + resolution: {integrity: sha512-935uAjAS8UAeXThqHfYVr4HEAp6nHJ2sximZKO1RzUTq5WoALMAhhGARl0+ecm6X+cqNUwIChJbjtaa6P/ML0w==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + graphql: 16.9.0 + resolve-from: 5.0.0 + tslib: 2.6.3 + dev: false + + /@graphql-tools/load@8.0.2(graphql@16.9.0): + resolution: {integrity: sha512-S+E/cmyVmJ3CuCNfDuNF2EyovTwdWfQScXv/2gmvJOti2rGD8jTt9GYVzXaxhblLivQR9sBUCNZu/w7j7aXUCA==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/schema': 10.0.6(graphql@16.9.0) + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + graphql: 16.9.0 + p-limit: 3.1.0 + tslib: 2.6.3 + dev: false + + /@graphql-tools/merge@9.0.7(graphql@16.9.0): + resolution: {integrity: sha512-lbTrIuXIbUSmSumHkPRY1QX0Z8JEtmRhnIrkH7vkfeEmf0kNn/nCWvJwqokm5U7L+a+DA1wlRM4slIlbfXjJBA==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + graphql: 16.9.0 + tslib: 2.6.3 + dev: false + + /@graphql-tools/optimize@1.4.0(graphql@16.9.0): + resolution: {integrity: sha512-dJs/2XvZp+wgHH8T5J2TqptT9/6uVzIYvA6uFACha+ufvdMBedkfR4b4GbT8jAKLRARiqRTxy3dctnwkTM2tdw==} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + graphql: 16.9.0 + tslib: 2.6.3 + dev: false + + /@graphql-tools/optimize@2.0.0(graphql@16.9.0): + resolution: {integrity: sha512-nhdT+CRGDZ+bk68ic+Jw1OZ99YCDIKYA5AlVAnBHJvMawSx9YQqQAIj4refNc1/LRieGiuWvhbG3jvPVYho0Dg==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + graphql: 16.9.0 + tslib: 2.6.3 + dev: false + + /@graphql-tools/relay-operation-optimizer@6.5.18(graphql@16.9.0): + resolution: {integrity: sha512-mc5VPyTeV+LwiM+DNvoDQfPqwQYhPV/cl5jOBjTgSniyaq8/86aODfMkrE2OduhQ5E00hqrkuL2Fdrgk0w1QJg==} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@ardatan/relay-compiler': 12.0.0(graphql@16.9.0) + '@graphql-tools/utils': 9.2.1(graphql@16.9.0) + graphql: 16.9.0 + tslib: 2.6.3 + transitivePeerDependencies: + - encoding + - supports-color + dev: false + + /@graphql-tools/relay-operation-optimizer@7.0.1(graphql@16.9.0): + resolution: {integrity: sha512-y0ZrQ/iyqWZlsS/xrJfSir3TbVYJTYmMOu4TaSz6F4FRDTQ3ie43BlKkhf04rC28pnUOS4BO9pDcAo1D30l5+A==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@ardatan/relay-compiler': 12.0.0(graphql@16.9.0) + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + graphql: 16.9.0 + tslib: 2.6.3 + transitivePeerDependencies: + - encoding + - supports-color + dev: false + + /@graphql-tools/schema@10.0.6(graphql@16.9.0): + resolution: {integrity: sha512-EIJgPRGzpvDFEjVp+RF1zNNYIC36BYuIeZ514jFoJnI6IdxyVyIRDLx/ykgMdaa1pKQerpfdqDnsF4JnZoDHSQ==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/merge': 9.0.7(graphql@16.9.0) + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + graphql: 16.9.0 + tslib: 2.6.3 + value-or-promise: 1.0.12 + dev: false + + /@graphql-tools/stitch@9.2.10(graphql@16.9.0): + resolution: {integrity: sha512-p4BOr6YTYZ9xjnHtrd6AsNR9Y2XtRSroSEEdOwv3KTHQLFhOD9wiLxb+UlKiHYm2jtTvL4wl6+TWV9dKCeNQ3g==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/batch-delegate': 9.0.3(graphql@16.9.0) + '@graphql-tools/delegate': 10.0.21(graphql@16.9.0) + '@graphql-tools/executor': 1.3.1(graphql@16.9.0) + '@graphql-tools/merge': 9.0.7(graphql@16.9.0) + '@graphql-tools/schema': 10.0.6(graphql@16.9.0) + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + '@graphql-tools/wrap': 10.0.5(graphql@16.9.0) + graphql: 16.9.0 + tslib: 2.6.3 + value-or-promise: 1.0.12 + dev: false + + /@graphql-tools/stitching-directives@3.1.2(graphql@16.9.0): + resolution: {integrity: sha512-c+udtRV+9IROJhbanoWH15Esb65E9VK5/VTVkV7XbhTpK+Id2X9qAUMCYTxHjexAOnZ8H+hGQpfNAHKdZ4F1QQ==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/delegate': 10.0.21(graphql@16.9.0) + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + graphql: 16.9.0 + tslib: 2.6.3 + dev: false + + /@graphql-tools/url-loader@8.0.2(@types/node@22.0.2)(graphql@16.9.0): + resolution: {integrity: sha512-1dKp2K8UuFn7DFo1qX5c1cyazQv2h2ICwA9esHblEqCYrgf69Nk8N7SODmsfWg94OEaI74IqMoM12t7eIGwFzQ==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@ardatan/sync-fetch': 0.0.1 + '@graphql-tools/delegate': 10.0.21(graphql@16.9.0) + '@graphql-tools/executor-graphql-ws': 1.2.0(graphql@16.9.0) + '@graphql-tools/executor-http': 1.1.6(@types/node@22.0.2)(graphql@16.9.0) + '@graphql-tools/executor-legacy-ws': 1.1.0(graphql@16.9.0) + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + '@graphql-tools/wrap': 10.0.5(graphql@16.9.0) + '@types/ws': 8.5.12 + '@whatwg-node/fetch': 0.9.21 + graphql: 16.9.0 + isomorphic-ws: 5.0.0(ws@8.18.0) + tslib: 2.6.3 + value-or-promise: 1.0.12 + ws: 8.18.0 + transitivePeerDependencies: + - '@types/node' + - bufferutil + - encoding + - utf-8-validate + dev: false + + /@graphql-tools/utils@10.5.4(graphql@16.9.0): + resolution: {integrity: sha512-XHnyCWSlg1ccsD8s0y6ugo5GZ5TpkTiFVNPSYms5G0s6Z/xTuSmiLBfeqgkfaCwLmLaQnRCmNDL2JRnqc2R5bQ==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-typed-document-node/core': 3.2.0(graphql@16.9.0) + cross-inspect: 1.0.1 + dset: 3.1.4 + graphql: 16.9.0 + tslib: 2.6.3 + dev: false + + /@graphql-tools/utils@8.13.1(graphql@16.9.0): + resolution: {integrity: sha512-qIh9yYpdUFmctVqovwMdheVNJqFh+DQNWIhX87FJStfXYnmweBUDATok9fWPleKeFwxnW8IapKmY8m8toJEkAw==} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + graphql: 16.9.0 + tslib: 2.6.3 + dev: false + + /@graphql-tools/utils@9.2.1(graphql@16.9.0): + resolution: {integrity: sha512-WUw506Ql6xzmOORlriNrD6Ugx+HjVgYxt9KCXD9mHAak+eaXSwuGGPyE60hy9xaDEoXKBsG7SkG69ybitaVl6A==} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-typed-document-node/core': 3.2.0(graphql@16.9.0) + graphql: 16.9.0 + tslib: 2.6.3 + dev: false + + /@graphql-tools/wrap@10.0.5(graphql@16.9.0): + resolution: {integrity: sha512-Cbr5aYjr3HkwdPvetZp1cpDWTGdD1Owgsb3z/ClzhmrboiK86EnQDxDvOJiQkDCPWE9lNBwj8Y4HfxroY0D9DQ==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + '@graphql-tools/delegate': 10.0.21(graphql@16.9.0) + '@graphql-tools/schema': 10.0.6(graphql@16.9.0) + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + graphql: 16.9.0 + tslib: 2.6.3 + value-or-promise: 1.0.12 + dev: false + + /@graphql-typed-document-node/core@3.2.0(graphql@16.9.0): + resolution: {integrity: sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==} + peerDependencies: + graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + dependencies: + graphql: 16.9.0 + dev: false + + /@graphql-yoga/logger@2.0.0: + resolution: {integrity: sha512-Mg8psdkAp+YTG1OGmvU+xa6xpsAmSir0hhr3yFYPyLNwzUj95DdIwsMpKadDj9xDpYgJcH3Hp/4JMal9DhQimA==} + engines: {node: '>=18.0.0'} + dependencies: + tslib: 2.6.3 + dev: false + + /@graphql-yoga/plugin-persisted-operations@3.7.0(@graphql-tools/utils@10.5.4)(graphql-yoga@5.7.0)(graphql@16.9.0): + resolution: {integrity: sha512-jfr+rIZBXbFxUO3j87u+VWWwyzIEn4SqSogRexyTFGhFb8hott8UALf/jOBEtZUIyHzsO3O1TN1pG+TPbQFkHA==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@graphql-tools/utils': ^10.0.0 + graphql: ^15.2.0 || ^16.0.0 + graphql-yoga: ^5.7.0 + dependencies: + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + graphql: 16.9.0 + graphql-yoga: 5.7.0(graphql@16.9.0) + dev: false + + /@graphql-yoga/subscription@5.0.1: + resolution: {integrity: sha512-1wCB1DfAnaLzS+IdoOzELGGnx1ODEg9nzQXFh4u2j02vAnne6d+v4A7HIH9EqzVdPLoAaMKXCZUUdKs+j3z1fg==} + engines: {node: '>=18.0.0'} + dependencies: + '@graphql-yoga/typed-event-target': 3.0.0 + '@repeaterjs/repeater': 3.0.6 + '@whatwg-node/events': 0.1.2 + tslib: 2.6.3 + dev: false + + /@graphql-yoga/typed-event-target@3.0.0: + resolution: {integrity: sha512-w+liuBySifrstuHbFrHoHAEyVnDFVib+073q8AeAJ/qqJfvFvAwUPLLtNohR/WDVRgSasfXtl3dcNuVJWN+rjg==} + engines: {node: '>=18.0.0'} + dependencies: + '@repeaterjs/repeater': 3.0.6 + tslib: 2.6.3 + dev: false + + /@hapi/hoek@9.3.0: + resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==} + dev: false + + /@hapi/topo@5.1.0: + resolution: {integrity: sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==} + dependencies: + '@hapi/hoek': 9.3.0 + dev: false + + /@humanwhocodes/config-array@0.11.14: + resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} + engines: {node: '>=10.10.0'} + dependencies: + '@humanwhocodes/object-schema': 2.0.3 + debug: 4.3.4(supports-color@8.1.1) + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@humanwhocodes/module-importer@1.0.1: + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + dev: true + + /@humanwhocodes/object-schema@2.0.3: + resolution: {integrity: sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==} + dev: true + + /@img/sharp-darwin-arm64@0.33.4: + resolution: {integrity: sha512-p0suNqXufJs9t3RqLBO6vvrgr5OhgbWp76s5gTRvdmxmuv9E1rcaqGUsl3l4mKVmXPkTkTErXediAui4x+8PSA==} + engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + optionalDependencies: + '@img/sharp-libvips-darwin-arm64': 1.0.2 + dev: false + optional: true + + /@img/sharp-darwin-x64@0.33.4: + resolution: {integrity: sha512-0l7yRObwtTi82Z6ebVI2PnHT8EB2NxBgpK2MiKJZJ7cz32R4lxd001ecMhzzsZig3Yv9oclvqqdV93jo9hy+Dw==} + engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [x64] + os: [darwin] + requiresBuild: true + optionalDependencies: + '@img/sharp-libvips-darwin-x64': 1.0.2 + dev: false + optional: true + + /@img/sharp-libvips-darwin-arm64@1.0.2: + resolution: {integrity: sha512-tcK/41Rq8IKlSaKRCCAuuY3lDJjQnYIW1UXU1kxcEKrfL8WR7N6+rzNoOxoQRJWTAECuKwgAHnPvqXGN8XfkHA==} + engines: {macos: '>=11', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@img/sharp-libvips-darwin-x64@1.0.2: + resolution: {integrity: sha512-Ofw+7oaWa0HiiMiKWqqaZbaYV3/UGL2wAPeLuJTx+9cXpCRdvQhCLG0IH8YGwM0yGWGLpsF4Su9vM1o6aer+Fw==} + engines: {macos: '>=10.13', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: false + optional: true + + /@img/sharp-libvips-linux-arm64@1.0.2: + resolution: {integrity: sha512-x7kCt3N00ofFmmkkdshwj3vGPCnmiDh7Gwnd4nUwZln2YjqPxV1NlTyZOvoDWdKQVDL911487HOueBvrpflagw==} + engines: {glibc: '>=2.26', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@img/sharp-libvips-linux-arm@1.0.2: + resolution: {integrity: sha512-iLWCvrKgeFoglQxdEwzu1eQV04o8YeYGFXtfWU26Zr2wWT3q3MTzC+QTCO3ZQfWd3doKHT4Pm2kRmLbupT+sZw==} + engines: {glibc: '>=2.28', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: false + optional: true + + /@img/sharp-libvips-linux-s390x@1.0.2: + resolution: {integrity: sha512-cmhQ1J4qVhfmS6szYW7RT+gLJq9dH2i4maq+qyXayUSn9/3iY2ZeWpbAgSpSVbV2E1JUL2Gg7pwnYQ1h8rQIog==} engines: {glibc: '>=2.28', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [s390x] os: [linux] @@ -3515,7 +4812,6 @@ packages: strip-ansi-cjs: /strip-ansi@6.0.1 wrap-ansi: 8.1.0 wrap-ansi-cjs: /wrap-ansi@7.0.0 - dev: true /@isaacs/ttlcache@1.4.1: resolution: {integrity: sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==} @@ -3628,6 +4924,10 @@ packages: '@jridgewell/sourcemap-codec': 1.5.0 dev: true + /@kamilkisiela/fast-url-parser@1.1.4: + resolution: {integrity: sha512-gbkePEBupNydxCelHCESvFSFM8XPh1Zs/OAVRW/rKpEqPAl5PbOM90Si8mv9bvnR53uPD2s/FiRxdvSejpRJew==} + dev: false + /@lit-labs/ssr-dom-shim@1.2.0: resolution: {integrity: sha512-yWJKmpGE6lUURKAaIltoPIE/wrbY3TEkqQt+X0m+7fQNnAv0keydnYvbiJFP1PnMhizmIWRWOG5KLhYyc/xl+g==} dev: false @@ -3638,6 +4938,26 @@ packages: '@lit-labs/ssr-dom-shim': 1.2.0 dev: false + /@mapbox/node-pre-gyp@1.0.11: + resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==} + hasBin: true + requiresBuild: true + dependencies: + detect-libc: 2.0.3 + https-proxy-agent: 5.0.1 + make-dir: 3.1.0 + node-fetch: 2.7.0 + nopt: 5.0.0 + npmlog: 5.0.1 + rimraf: 3.0.2 + semver: 7.6.3 + tar: 6.2.1 + transitivePeerDependencies: + - encoding + - supports-color + dev: false + optional: true + /@metamask/eth-json-rpc-provider@1.0.1: resolution: {integrity: sha512-whiUMPlAOrVGmX8aKYVPvlKyG4CpQXiNNyt74vE1xb5sPvmx5oA7B/kOi/JdBvhGQq97U1/AVdXEdk2zkP8qyA==} engines: {node: '>=14.0.0'} @@ -4538,6 +5858,30 @@ packages: - utf-8-validate dev: true + /@npmcli/agent@2.2.2: + resolution: {integrity: sha512-OrcNPXdpSl9UX7qPVRWbmWMCSXrcDa2M9DvrbOTj7ao1S4PlqVFYv9/yLKMkrJKZ/V5A/kDBC690or307i26Og==} + engines: {node: ^16.14.0 || >=18.0.0} + requiresBuild: true + dependencies: + agent-base: 7.1.1 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.5 + lru-cache: 10.4.3 + socks-proxy-agent: 8.0.4 + transitivePeerDependencies: + - supports-color + dev: false + optional: true + + /@npmcli/fs@3.1.1: + resolution: {integrity: sha512-q9CRWjpHCMIh5sVyefoD1cA7PkvILqCZsnSOEUUivORLjxCO/Irmue2DprETiNgEqktDBZaM1Bi+jrarx1XdCg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + requiresBuild: true + dependencies: + semver: 7.6.3 + dev: false + optional: true + /@oclif/core@2.16.0(@types/node@22.0.2)(typescript@5.5.4): resolution: {integrity: sha512-dL6atBH0zCZl1A1IXCKJgLPrM/wR7K+Wi401E/IvqsK8m2iCHW+0TEOGrans/cuN3oTW+uxIyJFHJ8Im0k4qBw==} engines: {node: '>=14.0.0'} @@ -5089,7 +6433,6 @@ packages: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} requiresBuild: true - dev: true optional: true /@protobufjs/aspromise@1.1.2: @@ -5623,6 +6966,10 @@ packages: react-dom: 18.3.1(react@18.3.1) dev: false + /@repeaterjs/repeater@3.0.6: + resolution: {integrity: sha512-Javneu5lsuhwNCryN+pXH93VPQ8g0dBX7wItHFgYiwQmzE1sVdg5tWHiOgHywzL2W21XQopa7IwIEnNbmeUJYA==} + dev: false + /@rescript/std@9.0.0: resolution: {integrity: sha512-zGzFsgtZ44mgL4Xef2gOy1hrRVdrs9mcxCOOKZrIPsmbZW14yTkaF591GXxpQvjXiHtgZ/iA9qLyWH6oSReIxQ==} dev: true @@ -7123,6 +8470,12 @@ packages: '@types/node': 22.0.2 dev: true + /@types/ws@8.5.12: + resolution: {integrity: sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==} + dependencies: + '@types/node': 22.0.2 + dev: false + /@types/yargs-parser@21.0.3: resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} dev: false @@ -7502,6 +8855,29 @@ packages: - react dev: false + /@wagmi/core@2.13.5(@types/react@18.3.3)(react@18.3.1)(typescript@5.5.4)(viem@2.18.7): + resolution: {integrity: sha512-lvX/hApJTSA/H2kOklokjIYiUpnT8CpBH80GeOiKxU0CGK1wNHTu20GRTCy0GF1t7jkNwPSG3m0SmnXmgYMmHw==} + peerDependencies: + '@tanstack/query-core': '>=5.0.0' + typescript: '>=5.0.4' + viem: 2.x + peerDependenciesMeta: + '@tanstack/query-core': + optional: true + typescript: + optional: true + dependencies: + eventemitter3: 5.0.1 + mipd: 0.0.7(typescript@5.5.4) + typescript: 5.5.4 + viem: 2.18.7(typescript@5.5.4) + zustand: 4.4.1(@types/react@18.3.3)(react@18.3.1) + transitivePeerDependencies: + - '@types/react' + - immer + - react + dev: false + /@walletconnect/core@2.14.0: resolution: {integrity: sha512-E/dgBM9q3judXnTfZQ5ILvDpeSdDpabBLsXtYXa3Nyc26cfNplfLJ2nXm9FgtTdhM1nZ7yx4+zDPiXawBRZl2g==} dependencies: @@ -7875,10 +9251,24 @@ packages: tslib: 1.14.1 dev: false + /@whatwg-node/disposablestack@0.0.5: + resolution: {integrity: sha512-9lXugdknoIequO4OYvIjhygvfSEgnO8oASLqLelnDhkRjgBZhc39shC3QSlZuyDO9bgYSIVa2cHAiN+St3ty4w==} + engines: {node: '>=18.0.0'} + dependencies: + tslib: 2.6.3 + dev: false + /@whatwg-node/events@0.0.3: resolution: {integrity: sha512-IqnKIDWfXBJkvy/k6tzskWTc2NK3LcqHlb+KHGCrjOCH4jfQckRX0NAiIcC/vIqQkzLYw2r2CTSwAxcrtcD6lA==} dev: true + /@whatwg-node/events@0.1.2: + resolution: {integrity: sha512-ApcWxkrs1WmEMS2CaLLFUEem/49erT3sxIVjpzU5f6zmVcnijtDSrhoK2zVobOIikZJdH63jdAXOrvjf6eOUNQ==} + engines: {node: '>=18.0.0'} + dependencies: + tslib: 2.6.3 + dev: false + /@whatwg-node/fetch@0.8.8: resolution: {integrity: sha512-CdcjGC2vdKhc13KKxgsc6/616BQ7ooDIgPeTuAiE8qfCnS0mGzcfCOoZXypQSz73nxI+GWc7ZReIAVhxoE1KCg==} dependencies: @@ -7889,15 +9279,86 @@ packages: web-streams-polyfill: 3.3.3 dev: true + /@whatwg-node/fetch@0.9.21: + resolution: {integrity: sha512-Wt0jPb+04JjobK0pAAN7mEHxVHcGA9HoP3OyCsZtyAecNQeADXCZ1MihFwVwjsgaRYuGVmNlsCmLxlG6mor8Gw==} + engines: {node: '>=18.0.0'} + dependencies: + '@whatwg-node/node-fetch': 0.5.26 + urlpattern-polyfill: 10.0.0 + dev: false + /@whatwg-node/node-fetch@0.3.6: resolution: {integrity: sha512-w9wKgDO4C95qnXZRwZTfCmLWqyRnooGjcIwG0wADWjw9/HN0p7dtvtgSvItZtUyNteEvgTrd8QojNEqV6DAGTA==} dependencies: - '@whatwg-node/events': 0.0.3 - busboy: 1.6.0 - fast-querystring: 1.1.2 - fast-url-parser: 1.1.3 + '@whatwg-node/events': 0.0.3 + busboy: 1.6.0 + fast-querystring: 1.1.2 + fast-url-parser: 1.1.3 + tslib: 2.6.3 + dev: true + + /@whatwg-node/node-fetch@0.5.26: + resolution: {integrity: sha512-4jXDeZ4IH4bylZ6wu14VEx0aDXXhrN4TC279v9rPmn08g4EYekcYf8wdcOOnS9STjDkb6x77/6xBUTqxGgjr8g==} + engines: {node: '>=18.0.0'} + dependencies: + '@kamilkisiela/fast-url-parser': 1.1.4 + busboy: 1.6.0 + fast-querystring: 1.1.2 + tslib: 2.6.3 + dev: false + + /@whatwg-node/server@0.9.49: + resolution: {integrity: sha512-3KzLXw80gWnTsQ746G/LFdCThTPfDodjQs4PnmoNuPa6XUOl4HWq8TlJpxtmnEEB+y+UYLal+3VQ68dtYlbUDQ==} + engines: {node: '>=18.0.0'} + dependencies: + '@whatwg-node/fetch': 0.9.21 + tslib: 2.6.3 + dev: false + + /@wry/caches@1.0.1: + resolution: {integrity: sha512-bXuaUNLVVkD20wcGBWRyo7j9N3TxePEWFZj2Y+r9OoUzfqmavM84+mFykRicNsBqatba5JLay1t48wxaXaWnlA==} + engines: {node: '>=8'} + requiresBuild: true + dependencies: + tslib: 2.6.3 + dev: false + optional: true + + /@wry/context@0.7.4: + resolution: {integrity: sha512-jmT7Sb4ZQWI5iyu3lobQxICu2nC/vbUhP0vIdd6tHC9PTfenmRmuIFqktc6GH9cgi+ZHnsLWPvfSvc4DrYmKiQ==} + engines: {node: '>=8'} + requiresBuild: true + dependencies: + tslib: 2.6.3 + dev: false + optional: true + + /@wry/equality@0.5.7: + resolution: {integrity: sha512-BRFORjsTuQv5gxcXsuDXx6oGRhuVsEGwZy6LOzRRfgu+eSfxbhUQ9L9YtSEIuIjY/o7g3iWFjrc5eSY1GXP2Dw==} + engines: {node: '>=8'} + requiresBuild: true + dependencies: + tslib: 2.6.3 + dev: false + optional: true + + /@wry/trie@0.4.3: + resolution: {integrity: sha512-I6bHwH0fSf6RqQcnnXLJKhkSXG45MFral3GxPaY4uAl0LYDZM+YDVDAiU9bYwjTuysy1S0IeecWtmq1SZA3M1w==} + engines: {node: '>=8'} + requiresBuild: true + dependencies: + tslib: 2.6.3 + dev: false + optional: true + + /@wry/trie@0.5.0: + resolution: {integrity: sha512-FNoYzHawTMk/6KMQoEG5O4PuioX19UbwdQKF44yw0nLfOypfQdjtfZzo/UIJWAJ23sNIFbD1Ug9lbaDGMwbqQA==} + engines: {node: '>=8'} + requiresBuild: true + dependencies: tslib: 2.6.3 - dev: true + dev: false + optional: true /JSONStream@1.3.2: resolution: {integrity: sha512-mn0KSip7N4e0UDPZHnqDsHECo5uGQrixQKnAskOM1BIB8hd7QKbd6il8IPRPudPHOeHiECoCFqhyMaRO9+nWyA==} @@ -7917,7 +9378,13 @@ packages: /abbrev@1.0.9: resolution: {integrity: sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q==} - dev: true + + /abbrev@2.0.0: + resolution: {integrity: sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + requiresBuild: true + dev: false + optional: true /abitype@1.0.5(typescript@5.5.4): resolution: {integrity: sha512-YzDhti7cjlfaBhHutMaboYB21Ha3rXR9QTkNJFzYC4kC8YclaiwPBBBJY8ejFdu2wnJeZCVZSMlQJ7fi8S6hsw==} @@ -7990,7 +9457,6 @@ packages: debug: 4.3.6(supports-color@8.1.1) transitivePeerDependencies: - supports-color - dev: true /agent-base@7.1.1: resolution: {integrity: sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==} @@ -8006,7 +9472,17 @@ packages: dependencies: clean-stack: 2.2.0 indent-string: 4.0.0 - dev: true + + /ajv-formats@3.0.1(ajv@8.13.0): + resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + dependencies: + ajv: 8.13.0 + dev: false /ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} @@ -8024,7 +9500,6 @@ packages: json-schema-traverse: 1.0.0 require-from-string: 2.0.2 uri-js: 4.4.1 - dev: true /amdefine@1.0.1: resolution: {integrity: sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==} @@ -8093,7 +9568,6 @@ packages: /ansi-regex@6.0.1: resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} engines: {node: '>=12'} - dev: true /ansi-styles@3.2.1: resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} @@ -8114,7 +9588,6 @@ packages: /ansi-styles@6.2.1: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} - dev: true /ansicolors@0.3.2: resolution: {integrity: sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==} @@ -8158,6 +9631,31 @@ packages: resolution: {integrity: sha512-Quji6+8kLBC3NnBeo14nPDq0+2jUs5s3/xEye+udFHumHhRk4M7aAMXp/PBJqkKYGuuyR9M/6Dq7d2AViiGmhw==} dev: false + /aproba@2.0.0: + resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} + requiresBuild: true + dev: false + optional: true + + /are-we-there-yet@2.0.0: + resolution: {integrity: sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==} + engines: {node: '>=10'} + deprecated: This package is no longer supported. + requiresBuild: true + dependencies: + delegates: 1.0.0 + readable-stream: 3.6.2 + dev: false + optional: true + + /are-we-there-yet@4.0.2: + resolution: {integrity: sha512-ncSWAawFhKMJDTdoAeOV+jyW1VCMj5QIAwULIBV0SSR7B/RLPPEQiknKcg/RIIZlUQrxELpsxMiTUoAQ4sIUyg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + deprecated: This package is no longer supported. + requiresBuild: true + dev: false + optional: true + /arg@4.1.3: resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} dev: true @@ -8169,7 +9667,6 @@ packages: /argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} - dev: true /aria-query@5.1.3: resolution: {integrity: sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==} @@ -8220,7 +9717,6 @@ packages: /array-union@2.1.0: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} - dev: true /array-uniq@1.0.3: resolution: {integrity: sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==} @@ -8396,6 +9892,11 @@ packages: engines: {node: '>=8.0.0'} dev: false + /auto-bind@4.0.0: + resolution: {integrity: sha512-Hdw8qdNiqdJ8LqT0iK0sVzkFbzg6fhnQqqfWhBDxcHZvU75+B+ayzTy8x+k5Ix0Y92XOhOUlx74ps+bA6BeYMQ==} + engines: {node: '>=8'} + dev: false + /available-typed-arrays@1.0.7: resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} engines: {node: '>= 0.4'} @@ -8483,6 +9984,10 @@ packages: - supports-color dev: false + /babel-plugin-syntax-trailing-function-commas@7.0.0-beta.0: + resolution: {integrity: sha512-Xj9XuRuz3nTSbaTXWv3itLOcxyF4oPD8douBBmj7U9BBC6nEBYfyOJYQMf/8PJAFotC62UY5dFfIGEPr7WswzQ==} + dev: false + /babel-plugin-transform-flow-enums@0.0.2(@babel/core@7.25.2): resolution: {integrity: sha512-g4aaCrDDOsWjbm0PUUeVnkcVd6AKJsVc/MbnPhEotEpkeJQP6b8nzewohQi7+QS8UyPehOhGWn0nOwjvWpmMvQ==} dependencies: @@ -8491,6 +9996,43 @@ packages: - '@babel/core' dev: false + /babel-preset-fbjs@3.4.0(@babel/core@7.25.2): + resolution: {integrity: sha512-9ywCsCvo1ojrw0b+XYk7aFvTH6D9064t0RIL1rtMf3nsa02Xw41MS7sZw216Im35xj/UY0PDBQsa1brUDDF1Ow==} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.25.2 + '@babel/plugin-proposal-class-properties': 7.18.6(@babel/core@7.25.2) + '@babel/plugin-proposal-object-rest-spread': 7.20.7(@babel/core@7.25.2) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.25.2) + '@babel/plugin-syntax-flow': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-syntax-jsx': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.25.2) + '@babel/plugin-transform-arrow-functions': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-block-scoped-functions': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-block-scoping': 7.25.0(@babel/core@7.25.2) + '@babel/plugin-transform-classes': 7.25.0(@babel/core@7.25.2) + '@babel/plugin-transform-computed-properties': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-destructuring': 7.24.8(@babel/core@7.25.2) + '@babel/plugin-transform-flow-strip-types': 7.25.2(@babel/core@7.25.2) + '@babel/plugin-transform-for-of': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-function-name': 7.25.1(@babel/core@7.25.2) + '@babel/plugin-transform-literals': 7.25.2(@babel/core@7.25.2) + '@babel/plugin-transform-member-expression-literals': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-modules-commonjs': 7.24.8(@babel/core@7.25.2) + '@babel/plugin-transform-object-super': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-parameters': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-property-literals': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-react-display-name': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-react-jsx': 7.25.2(@babel/core@7.25.2) + '@babel/plugin-transform-shorthand-properties': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-spread': 7.24.7(@babel/core@7.25.2) + '@babel/plugin-transform-template-literals': 7.24.7(@babel/core@7.25.2) + babel-plugin-syntax-trailing-function-commas: 7.0.0-beta.0 + transitivePeerDependencies: + - supports-color + dev: false + /balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} @@ -8823,6 +10365,26 @@ packages: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} + /cacache@18.0.4: + resolution: {integrity: sha512-B+L5iIa9mgcjLbliir2th36yEwPftrzteHYujzsx3dFP/31GCHcIeS8f5MGd80odLOjaOvSpU3EEAmRQptkxLQ==} + engines: {node: ^16.14.0 || >=18.0.0} + requiresBuild: true + dependencies: + '@npmcli/fs': 3.1.1 + fs-minipass: 3.0.3 + glob: 10.4.5 + lru-cache: 10.4.3 + minipass: 7.1.2 + minipass-collect: 2.0.1 + minipass-flush: 1.0.5 + minipass-pipeline: 1.2.4 + p-map: 4.0.0 + ssri: 10.0.6 + tar: 6.2.1 + unique-filename: 3.0.0 + dev: false + optional: true + /cacheable-lookup@5.0.4: resolution: {integrity: sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==} engines: {node: '>=10.6.0'} @@ -8878,7 +10440,6 @@ packages: /callsites@3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} engines: {node: '>=6'} - dev: true /camel-case@3.0.0: resolution: {integrity: sha512-+MbKztAYHXPr1jNTSKQF52VpcFjwY5RkR7fxksV8Doo4KAYc5Fl4UJRgthBbTmEx8C54DqahhbLJkDwjI3PI/w==} @@ -8887,6 +10448,13 @@ packages: upper-case: 1.1.3 dev: true + /camel-case@4.1.2: + resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==} + dependencies: + pascal-case: 3.1.2 + tslib: 2.6.3 + dev: false + /camelcase@3.0.0: resolution: {integrity: sha512-4nhGqUkc4BqbBBB4Q6zLuD7lzzrHYrjKGeYaEji/3tFR5VdJu9v+LilhGIVe8wxEJPPOeWo7eg8dwY13TZ1BNg==} engines: {node: '>=0.10.0'} @@ -8925,6 +10493,14 @@ packages: resolution: {integrity: sha512-dRg00gudiBDDTmUhClSdv3hqRfpbOnU28IpI1T6PBTLWa+kOj0681C8uML3PifYfREuBrVjDGhL3adYpBT6spw==} dev: false + /capital-case@1.0.4: + resolution: {integrity: sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==} + dependencies: + no-case: 3.0.4 + tslib: 2.6.3 + upper-case-first: 2.0.2 + dev: false + /cardinal@2.1.1: resolution: {integrity: sha512-JSr5eOgoEymtYHBjNWyjrMqet9Am2miJhlfKNdqLp6zoeAh0KN5dRAcxlecj5mAJrmQomgiOBj35xHLrFjqBpw==} hasBin: true @@ -9023,6 +10599,36 @@ packages: ansi-styles: 4.3.0 supports-color: 7.2.0 + /change-case-all@1.0.14: + resolution: {integrity: sha512-CWVm2uT7dmSHdO/z1CXT/n47mWonyypzBbuCy5tN7uMg22BsfkhwT6oHmFCAk+gL1LOOxhdbB9SZz3J1KTY3gA==} + dependencies: + change-case: 4.1.2 + is-lower-case: 2.0.2 + is-upper-case: 2.0.2 + lower-case: 2.0.2 + lower-case-first: 2.0.2 + sponge-case: 1.0.1 + swap-case: 2.0.2 + title-case: 3.0.3 + upper-case: 2.0.2 + upper-case-first: 2.0.2 + dev: false + + /change-case-all@1.0.15: + resolution: {integrity: sha512-3+GIFhk3sNuvFAJKU46o26OdzudQlPNBCu1ZQi3cMeMHhty1bhDxu2WrEilVNYaGvqUtR1VSigFcJOiS13dRhQ==} + dependencies: + change-case: 4.1.2 + is-lower-case: 2.0.2 + is-upper-case: 2.0.2 + lower-case: 2.0.2 + lower-case-first: 2.0.2 + sponge-case: 1.0.1 + swap-case: 2.0.2 + title-case: 3.0.3 + upper-case: 2.0.2 + upper-case-first: 2.0.2 + dev: false + /change-case@3.0.2: resolution: {integrity: sha512-Mww+SLF6MZ0U6kdg11algyKd5BARbyM4TbFBepwowYSR5ClfQGCGtxNXgykpN0uF/bstWeaGDT4JWaDh8zWAHA==} dependencies: @@ -9046,6 +10652,23 @@ packages: upper-case-first: 1.1.2 dev: true + /change-case@4.1.2: + resolution: {integrity: sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==} + dependencies: + camel-case: 4.1.2 + capital-case: 1.0.4 + constant-case: 3.0.4 + dot-case: 3.0.4 + header-case: 2.0.4 + no-case: 3.0.4 + param-case: 3.0.4 + pascal-case: 3.1.2 + path-case: 3.0.4 + sentence-case: 3.0.4 + snake-case: 3.0.4 + tslib: 2.6.3 + dev: false + /charenc@0.0.2: resolution: {integrity: sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==} dev: true @@ -9121,7 +10744,6 @@ packages: /chownr@2.0.0: resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} engines: {node: '>=10'} - dev: true /chrome-launcher@0.15.2: resolution: {integrity: sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ==} @@ -9176,7 +10798,6 @@ packages: /clean-stack@2.2.0: resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} engines: {node: '>=6'} - dev: true /clean-stack@3.0.1: resolution: {integrity: sha512-lR9wNiMRcVQjSB3a7xXGLuz4cr4wJuuXlaAEbRutGowQTmlp7R72/DOgN21e8jdwblMWl9UOJMJXarX94pzKdg==} @@ -9333,6 +10954,13 @@ packages: simple-swizzle: 0.2.2 dev: false + /color-support@1.1.3: + resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} + hasBin: true + requiresBuild: true + dev: false + optional: true + /color@4.2.3: resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} engines: {node: '>=12.5.0'} @@ -9395,6 +11023,11 @@ packages: resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} engines: {node: ^12.20.0 || >=14} + /common-tags@1.8.2: + resolution: {integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==} + engines: {node: '>=4.0.0'} + dev: false + /commondir@1.0.1: resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} dev: false @@ -9458,6 +11091,12 @@ packages: engines: {node: ^14.18.0 || >=16.10.0} dev: false + /console-control-strings@1.1.0: + resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} + requiresBuild: true + dev: false + optional: true + /constant-case@2.0.0: resolution: {integrity: sha512-eS0N9WwmjTqrOmR3o83F5vW8Z+9R1HnVz3xmzT2PMFug9ly+Au/fxRWlEBSb6LcZwspSsEn9Xs1uw9YgzAg1EQ==} dependencies: @@ -9465,6 +11104,14 @@ packages: upper-case: 1.1.3 dev: true + /constant-case@3.0.4: + resolution: {integrity: sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==} + dependencies: + no-case: 3.0.4 + tslib: 2.6.3 + upper-case: 2.0.2 + dev: false + /content-disposition@0.5.4: resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} engines: {node: '>= 0.6'} @@ -9569,6 +11216,22 @@ packages: typescript: 5.5.4 dev: true + /cosmiconfig@9.0.0(typescript@5.5.4): + resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + env-paths: 2.2.1 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + parse-json: 5.2.0 + typescript: 5.5.4 + dev: false + /crc-32@1.2.2: resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==} engines: {node: '>=0.8'} @@ -9613,6 +11276,13 @@ packages: transitivePeerDependencies: - encoding + /cross-inspect@1.0.1: + resolution: {integrity: sha512-Pcw1JTvZLSJH83iiGWt6fRcT+BjZlCDRVwYLbUcHzv/CRpB7r0MlSrGbIyQvVSNyGnbt7G4AXuyCiDR3POvZ1A==} + engines: {node: '>=16.0.0'} + dependencies: + tslib: 2.6.3 + dev: false + /cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} @@ -9768,6 +11438,10 @@ packages: is-data-view: 1.0.1 dev: true + /dataloader@2.2.2: + resolution: {integrity: sha512-8YnDaaf7N3k/q5HnTJVuzSyLETjoZjVmHc4AeKAzOvKHEFQKcn64OKBfzHYtE9zGjctNM7V9I0MfnUVLpi7M5g==} + dev: false + /date-fns@2.30.0: resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==} engines: {node: '>=0.11'} @@ -9782,8 +11456,8 @@ packages: undici-types: 5.28.4 dev: true - /dayjs@1.11.12: - resolution: {integrity: sha512-Rt2g+nTbLlDWZTwwrIXjy9MeiZmSDI375FvZs72ngxx8PDC6YXOeR3q5LAuPzjZQxhiWdRKac7RKV+YyQYfYIg==} + /dayjs@1.11.13: + resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} dev: false /de-indent@1.0.2: @@ -9826,7 +11500,6 @@ packages: dependencies: ms: 2.1.2 supports-color: 8.1.1 - dev: true /debug@4.3.5: resolution: {integrity: sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==} @@ -9979,6 +11652,12 @@ packages: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} + /delegates@1.0.0: + resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} + requiresBuild: true + dev: false + optional: true + /denodeify@1.2.1: resolution: {integrity: sha512-KNTihKNmQENUZeKu5fzfpzRqR5S2VMp4gl9RFHiWzj9DfvYQPMJ6XHKNaQxaGCXwPk6y9yme3aUoaiAe+KX+vg==} dev: false @@ -9987,6 +11666,16 @@ packages: resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} engines: {node: '>= 0.8'} + /dependency-graph@0.11.0: + resolution: {integrity: sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==} + engines: {node: '>= 0.6.0'} + dev: false + + /dependency-graph@1.0.0: + resolution: {integrity: sha512-cW3gggJ28HZ/LExwxP2B++aiKxhJXMSIt9K48FOXQkm+vuG5gyatXnLsONRJdzO/7VfjDIiaOOa/bs4l464Lwg==} + engines: {node: '>=4'} + dev: false + /dequal@2.0.3: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} @@ -10048,7 +11737,6 @@ packages: engines: {node: '>=8'} dependencies: path-type: 4.0.0 - dev: true /dns-over-http-resolver@1.2.3(node-fetch@2.7.0): resolution: {integrity: sha512-miDiVSI6KSNbi4SVifzO/reD8rMnxgrlnkrlkugOLQpWQTe2qMdHsZp5DmfKjxNE+/T3VAAYLQUZMv9SMr6+AA==} @@ -10161,7 +11849,11 @@ packages: dependencies: no-case: 3.0.4 tslib: 2.6.2 - dev: true + + /dotenv@16.4.5: + resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} + engines: {node: '>=12'} + dev: false /dprint@0.47.2: resolution: {integrity: sha512-geUcVIIrmLaY+YtuOl4gD7J/QCjsXZa5gUqre9sO6cgH0X/Fa9heBN3l/AWVII6rKPw45ATuCSDWz1pyO+HkPQ==} @@ -10178,6 +11870,11 @@ packages: '@dprint/win32-x64': 0.47.2 dev: true + /dset@3.1.4: + resolution: {integrity: sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==} + engines: {node: '>=4'} + dev: false + /duplexify@4.1.3: resolution: {integrity: sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==} dependencies: @@ -10189,7 +11886,6 @@ packages: /eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - dev: true /ecc-jsbn@0.1.2: resolution: {integrity: sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==} @@ -10279,7 +11975,6 @@ packages: /emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - dev: true /encode-utf8@1.0.3: resolution: {integrity: sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw==} @@ -10293,7 +11988,6 @@ packages: resolution: {integrity: sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==} dependencies: iconv-lite: 0.6.3 - dev: true /end-of-stream@1.4.4: resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} @@ -10346,10 +12040,16 @@ packages: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} + /env-paths@2.2.0: + resolution: {integrity: sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA==} + engines: {node: '>=6'} + requiresBuild: true + dev: false + optional: true + /env-paths@2.2.1: resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} engines: {node: '>=6'} - dev: true /envinfo@7.13.0: resolution: {integrity: sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==} @@ -10357,6 +12057,12 @@ packages: hasBin: true dev: false + /err-code@2.0.3: + resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==} + requiresBuild: true + dev: false + optional: true + /err-code@3.0.1: resolution: {integrity: sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA==} dev: true @@ -11298,6 +13004,12 @@ packages: signal-exit: 4.1.0 strip-final-newline: 3.0.0 + /exponential-backoff@3.1.1: + resolution: {integrity: sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==} + requiresBuild: true + dev: false + optional: true + /express@4.18.2: resolution: {integrity: sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==} engines: {node: '>= 0.10.0'} @@ -11394,6 +13106,11 @@ packages: webextension-polyfill: 0.10.0 dev: false + /extract-files@11.0.0: + resolution: {integrity: sha512-FuoE1qtbJ4bBVvv94CC7s0oTnKUGvQs+Rjf1L2SJFfS+HTVVjhPFtehPdQ0JiGPqVNfSSZvL5yzHHQq2Z4WNhQ==} + engines: {node: ^12.20 || >= 14.13} + dev: false + /extsprintf@1.3.0: resolution: {integrity: sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==} engines: {'0': node >=0.6.0} @@ -11413,7 +13130,6 @@ packages: /fast-decode-uri-component@1.0.1: resolution: {integrity: sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==} - dev: true /fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} @@ -11436,6 +13152,18 @@ packages: resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} dev: true + /fast-json-stringify@5.16.1: + resolution: {integrity: sha512-KAdnLvy1yu/XrRtP+LJnxbBGrhN+xXu+gt3EUvZhYGKCr3lFHq/7UFJHHFgmJKoqlh6B40bZLEv7w46B0mqn1g==} + dependencies: + '@fastify/merge-json-schemas': 0.1.1 + ajv: 8.13.0 + ajv-formats: 3.0.1(ajv@8.13.0) + fast-deep-equal: 3.1.3 + fast-uri: 2.4.0 + json-schema-ref-resolver: 1.0.1 + rfdc: 1.4.1 + dev: false + /fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} dev: true @@ -11450,7 +13178,6 @@ packages: resolution: {integrity: sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==} dependencies: fast-decode-uri-component: 1.0.1 - dev: true /fast-redact@3.5.0: resolution: {integrity: sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==} @@ -11461,6 +13188,10 @@ packages: resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} dev: false + /fast-uri@2.4.0: + resolution: {integrity: sha512-ypuAmmMKInk5q7XcepxlnUWDLWv4GFtaJqAzWKqn62IpQ3pejtr5dTVbt3vwqVaMKmkNR55sTT+CqUKIaT21BA==} + dev: false + /fast-url-parser@1.1.3: resolution: {integrity: sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==} dependencies: @@ -11490,6 +13221,24 @@ packages: bser: 2.1.1 dev: false + /fbjs-css-vars@1.0.2: + resolution: {integrity: sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==} + dev: false + + /fbjs@3.0.5: + resolution: {integrity: sha512-ztsSx77JBtkuMrEypfhgc3cI0+0h+svqeie7xHbh1k/IKdcydnvadp/mUaGgjAOXQmQSxsqgaRhS3q9fy+1kxg==} + dependencies: + cross-fetch: 3.1.8 + fbjs-css-vars: 1.0.2 + loose-envify: 1.4.0 + object-assign: 4.1.1 + promise: 7.3.1 + setimmediate: 1.0.5 + ua-parser-js: 1.0.38 + transitivePeerDependencies: + - encoding + dev: false + /file-entry-cache@6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -11679,13 +13428,16 @@ packages: dependencies: is-callable: 1.2.7 + /foreach@2.0.6: + resolution: {integrity: sha512-k6GAGDyqLe9JaebCsFCoudPPWfihKu8pylYXRlqP1J7ms39iPoTtk2fviNglIeQEwdh0bQeKJ01ZPyuyQvKzwg==} + dev: false + /foreground-child@3.1.1: resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} engines: {node: '>=14'} dependencies: cross-spawn: 7.0.3 signal-exit: 4.1.0 - dev: true /forever-agent@0.6.1: resolution: {integrity: sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==} @@ -11813,7 +13565,15 @@ packages: engines: {node: '>= 8'} dependencies: minipass: 3.3.6 - dev: true + + /fs-minipass@3.0.3: + resolution: {integrity: sha512-XUBA9XClHbnJWSfBzjkm6RvPsyg3sryZt06BEQoXcF7EK/xpGaQYJgQKDJSUH5SGZ76Y7pFx1QBnXz09rU5Fbw==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + requiresBuild: true + dependencies: + minipass: 7.1.2 + dev: false + optional: true /fs-readdir-recursive@1.1.0: resolution: {integrity: sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==} @@ -11851,6 +13611,41 @@ packages: engines: {node: '>=8'} dev: false + /gauge@3.0.2: + resolution: {integrity: sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==} + engines: {node: '>=10'} + deprecated: This package is no longer supported. + requiresBuild: true + dependencies: + aproba: 2.0.0 + color-support: 1.1.3 + console-control-strings: 1.1.0 + has-unicode: 2.0.1 + object-assign: 4.1.1 + signal-exit: 3.0.7 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wide-align: 1.1.5 + dev: false + optional: true + + /gauge@5.0.2: + resolution: {integrity: sha512-pMaFftXPtiGIHCJHdcUUx9Rby/rFT/Kkt3fIIGCs+9PMDIljSyRiqraTlxNtBReJRDfUefpa263RQ3vnp5G/LQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + deprecated: This package is no longer supported. + requiresBuild: true + dependencies: + aproba: 2.0.0 + color-support: 1.1.3 + console-control-strings: 1.1.0 + has-unicode: 2.0.1 + signal-exit: 4.1.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + wide-align: 1.1.5 + dev: false + optional: true + /geist@1.3.1(next@14.2.5): resolution: {integrity: sha512-Q4gC1pBVPN+D579pBaz0TRRnGA4p9UK6elDY/xizXdFk/g4EKR5g0I+4p/Kj6gM0SajDBZ/0FvDV9ey9ud7BWw==} peerDependencies: @@ -11859,6 +13654,12 @@ packages: next: 14.2.5(@babel/core@7.25.2)(react-dom@18.3.1)(react@18.3.1) dev: false + /generate-function@2.3.1: + resolution: {integrity: sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==} + dependencies: + is-property: 1.0.2 + dev: false + /gensync@1.0.0-beta.2: resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} engines: {node: '>=6.9.0'} @@ -11985,7 +13786,19 @@ packages: minipass: 7.1.2 package-json-from-dist: 1.0.0 path-scurry: 1.11.1 - dev: true + + /glob@11.0.0: + resolution: {integrity: sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==} + engines: {node: 20 || >=22} + hasBin: true + dependencies: + foreground-child: 3.1.1 + jackspeak: 4.0.1 + minimatch: 10.0.1 + minipass: 7.1.2 + package-json-from-dist: 1.0.0 + path-scurry: 2.0.0 + dev: false /glob@5.0.15: resolution: {integrity: sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA==} @@ -12122,7 +13935,6 @@ packages: ignore: 5.3.1 merge2: 1.4.1 slash: 3.0.0 - dev: true /globrex@0.1.2: resolution: {integrity: sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==} @@ -12220,7 +14032,59 @@ packages: graphql: '*' dependencies: graphql: 16.9.0 - dev: true + + /graphql-jit@0.8.6(graphql@16.9.0): + resolution: {integrity: sha512-oVJteh/uYDpIA/M4UHrI+DmzPnX1zTD0a7Je++JA8q8P68L/KbuepimDyrT5FhL4HAq3filUxaFvfsL6/A4msw==} + peerDependencies: + graphql: '>=15' + dependencies: + '@graphql-typed-document-node/core': 3.2.0(graphql@16.9.0) + fast-json-stringify: 5.16.1 + generate-function: 2.3.1 + graphql: 16.9.0 + lodash.memoize: 4.1.2 + lodash.merge: 4.6.2 + lodash.mergewith: 4.6.2 + dev: false + + /graphql-tag@2.12.6(graphql@16.9.0): + resolution: {integrity: sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==} + engines: {node: '>=10'} + peerDependencies: + graphql: ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + dependencies: + graphql: 16.9.0 + tslib: 2.6.3 + dev: false + + /graphql-ws@5.16.0(graphql@16.9.0): + resolution: {integrity: sha512-Ju2RCU2dQMgSKtArPbEtsK5gNLnsQyTNIo/T7cZNp96niC1x0KdJNZV0TIoilceBPQwfb5itrGl8pkFeOUMl4A==} + engines: {node: '>=10'} + peerDependencies: + graphql: '>=0.11 <=16' + dependencies: + graphql: 16.9.0 + dev: false + + /graphql-yoga@5.7.0(graphql@16.9.0): + resolution: {integrity: sha512-QyGVvFAvGhMrzjJvhjsxsyoE+e4lNrj5f5qOsRYJuWIjyw7tHfbBvybZIwzNOGY0aB5sgA8BlVvu5hxjdKJ5tQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + graphql: ^15.2.0 || ^16.0.0 + dependencies: + '@envelop/core': 5.0.2 + '@graphql-tools/executor': 1.3.1(graphql@16.9.0) + '@graphql-tools/schema': 10.0.6(graphql@16.9.0) + '@graphql-tools/utils': 10.5.4(graphql@16.9.0) + '@graphql-yoga/logger': 2.0.0 + '@graphql-yoga/subscription': 5.0.1 + '@whatwg-node/fetch': 0.9.21 + '@whatwg-node/server': 0.9.49 + dset: 3.1.4 + graphql: 16.9.0 + lru-cache: 10.4.3 + tslib: 2.6.3 + dev: false /graphql@15.5.0: resolution: {integrity: sha512-OmaM7y0kaK31NKG31q4YbD2beNYa6jBBKtMFT6gLYJljHLJr42IqJ8KX08u3Li/0ifzTU5HjmoOOrwa5BRLeDA==} @@ -12230,7 +14094,6 @@ packages: /graphql@16.9.0: resolution: {integrity: sha512-GGTKBX4SD7Wdb8mqeDLni2oaRGYQWjWHGKPQ24ZMnUtKfcsVoiv4uX8+LJr1K6U5VW2Lu1BwJnj7uiori0YtRw==} engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} - dev: true /h3@1.12.0: resolution: {integrity: sha512-Zi/CcNeWBXDrFNlV0hUBJQR9F7a96RjMeAZweW/ZWkR9fuXrMcvKnSA63f/zZ9l0GgQOZDVHGvXivNN9PWOwhA==} @@ -12392,6 +14255,12 @@ packages: dependencies: has-symbols: 1.0.3 + /has-unicode@2.0.1: + resolution: {integrity: sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==} + requiresBuild: true + dev: false + optional: true + /hash-base@3.1.0: resolution: {integrity: sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==} engines: {node: '>=4'} @@ -12432,6 +14301,13 @@ packages: upper-case: 1.1.3 dev: true + /header-case@2.0.4: + resolution: {integrity: sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==} + dependencies: + capital-case: 1.0.4 + tslib: 2.6.3 + dev: false + /heap@0.2.7: resolution: {integrity: sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==} dev: true @@ -12482,6 +14358,14 @@ packages: minimalistic-assert: 1.0.1 minimalistic-crypto-utils: 1.0.1 + /hoist-non-react-statics@3.3.2: + resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} + requiresBuild: true + dependencies: + react-is: 16.13.1 + dev: false + optional: true + /hookable@5.5.3: resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==} @@ -12520,7 +14404,6 @@ packages: /http-cache-semantics@4.1.1: resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} - dev: true /http-errors@2.0.0: resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} @@ -12618,7 +14501,6 @@ packages: debug: 4.3.4(supports-color@8.1.1) transitivePeerDependencies: - supports-color - dev: true /https-proxy-agent@7.0.5: resolution: {integrity: sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==} @@ -12684,7 +14566,6 @@ packages: /ignore@5.3.1: resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} engines: {node: '>= 4'} - dev: true /image-size@1.1.1: resolution: {integrity: sha512-541xKlUw6jr/6gGuk92F+mYM5zaFAc5ahphvkqvNe2bQ6gVBkd6bfrmVJ2t4KDAfikAYZyIqTnktX3i6/aQDrQ==} @@ -12694,6 +14575,15 @@ packages: queue: 6.0.2 dev: false + /immediate@3.0.6: + resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} + dev: false + + /immutable@3.7.6: + resolution: {integrity: sha512-AizQPcaofEtO11RZhPPHBOJRdo/20MKQF9mBLnVkBoyHi1/zXK8fzVdnEpSV9gxqtnh6Qomfp3F0xT5qP/vThw==} + engines: {node: '>=0.8.0'} + dev: false + /immutable@4.2.1: resolution: {integrity: sha512-7WYV7Q5BTs0nlQm7tl92rDYYoyELLKHoDMBKhrxEoiV4mrfVdRz8hzPiYOzH7yWjzoVEamxRuAqhxL2PLRwZYQ==} dev: true @@ -12716,7 +14606,11 @@ packages: dependencies: parent-module: 1.0.1 resolve-from: 4.0.0 - dev: true + + /import-from@4.0.0: + resolution: {integrity: sha512-P9J71vT5nLlDeV8FHs5nNxaLbrpfAV5cF5srvbZfpwpcJoM/xZR3hiv+q+SAnuSmuGbXMWud063iIMx/V/EWZQ==} + engines: {node: '>=12.2'} + dev: false /import-lazy@4.0.0: resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} @@ -12730,7 +14624,6 @@ packages: /indent-string@4.0.0: resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} engines: {node: '>=8'} - dev: true /inflight@1.0.6: resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} @@ -12789,6 +14682,16 @@ packages: fp-ts: 1.19.3 dev: true + /ip-address@9.0.5: + resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==} + engines: {node: '>= 12'} + requiresBuild: true + dependencies: + jsbn: 1.1.0 + sprintf-js: 1.1.3 + dev: false + optional: true + /ip-regex@4.3.0: resolution: {integrity: sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==} engines: {node: '>=8'} @@ -12907,6 +14810,14 @@ packages: resolution: {integrity: sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==} dev: false + /is-absolute@1.0.0: + resolution: {integrity: sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==} + engines: {node: '>=0.10.0'} + dependencies: + is-relative: 1.0.0 + is-windows: 1.0.2 + dev: false + /is-arguments@1.1.1: resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} engines: {node: '>= 0.4'} @@ -13082,12 +14993,24 @@ packages: ip-regex: 4.3.0 dev: true + /is-lambda@1.0.1: + resolution: {integrity: sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==} + requiresBuild: true + dev: false + optional: true + /is-lower-case@1.1.3: resolution: {integrity: sha512-+5A1e/WJpLLXZEDlgz4G//WYSHyQBD32qa4Jd3Lw06qQlv3fJHnp3YIHjTQSGzHMgzmVKz2ZP3rBxTHkPw/lxA==} dependencies: lower-case: 1.1.4 dev: true + /is-lower-case@2.0.2: + resolution: {integrity: sha512-bVcMJy4X5Og6VZfdOZstSexlEy20Sr0k/p/b2IlQJlfdKAQuMpiv5w2Ccxb8sKdRUNAG1PnHVHjFSdRDVS6NlQ==} + dependencies: + tslib: 2.6.3 + dev: false + /is-map@2.0.3: resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} engines: {node: '>= 0.4'} @@ -13134,6 +15057,10 @@ packages: /is-potential-custom-element-name@1.0.1: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + /is-property@1.0.2: + resolution: {integrity: sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==} + dev: false + /is-regex@1.1.4: resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} engines: {node: '>= 0.4'} @@ -13142,6 +15069,13 @@ packages: has-tostringtag: 1.0.2 dev: true + /is-relative@1.0.0: + resolution: {integrity: sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==} + engines: {node: '>=0.10.0'} + dependencies: + is-unc-path: 1.0.0 + dev: false + /is-set@2.0.3: resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} engines: {node: '>= 0.4'} @@ -13186,6 +15120,13 @@ packages: resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} dev: true + /is-unc-path@1.0.0: + resolution: {integrity: sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==} + engines: {node: '>=0.10.0'} + dependencies: + unc-path-regex: 0.1.2 + dev: false + /is-unicode-supported@0.1.0: resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} engines: {node: '>=10'} @@ -13196,6 +15137,12 @@ packages: upper-case: 1.1.3 dev: true + /is-upper-case@2.0.2: + resolution: {integrity: sha512-44pxmxAvnnAOwBg4tHPnkfvgjPwbc5QIsSstNU+YcJ1ovxVzCWpSGosPJOZh/a1tdl81fbgnLc9LLv+x2ywbPQ==} + dependencies: + tslib: 2.6.3 + dev: false + /is-utf8@0.2.1: resolution: {integrity: sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==} dev: true @@ -13223,6 +15170,11 @@ packages: resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==} engines: {node: '>=12.13'} + /is-windows@1.0.2: + resolution: {integrity: sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==} + engines: {node: '>=0.10.0'} + dev: false + /is-wsl@1.1.0: resolution: {integrity: sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==} engines: {node: '>=4'} @@ -13265,7 +15217,6 @@ packages: /isexe@3.1.1: resolution: {integrity: sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==} engines: {node: '>=16'} - dev: true /iso-url@1.2.1: resolution: {integrity: sha512-9JPDgCN4B7QPkLtYAAOrEuAWvP9rWvR5offAr0/SeF046wIkglqH3VXgYYP6NcsKslH80UIVgmPqNe3j7tG2ng==} @@ -13294,6 +15245,14 @@ packages: ws: 7.5.10 dev: true + /isomorphic-ws@5.0.0(ws@8.18.0): + resolution: {integrity: sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==} + peerDependencies: + ws: '*' + dependencies: + ws: 8.18.0 + dev: false + /isows@1.0.4(ws@8.17.1): resolution: {integrity: sha512-hEzjY+x9u9hPmBom9IIAqdJCwNLax+xrPb51vEPpERoFlIxgmZcHzsT5jKG06nvInKOBGvReAVz80Umed5CczQ==} peerDependencies: @@ -13402,7 +15361,15 @@ packages: '@isaacs/cliui': 8.0.2 optionalDependencies: '@pkgjs/parseargs': 0.11.0 - dev: true + + /jackspeak@4.0.1: + resolution: {integrity: sha512-cub8rahkh0Q/bw1+GxP7aeSe29hHHn2V4m29nnDlvCdlgU+3UGxkZp7Z53jLUdpX3jdTO0nJZUDl3xvbWc2Xog==} + engines: {node: 20 || >=22} + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + dev: false /jake@10.9.2: resolution: {integrity: sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==} @@ -13564,12 +15531,17 @@ packages: hasBin: true dependencies: argparse: 2.0.1 - dev: true /jsbn@0.1.1: resolution: {integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==} dev: true + /jsbn@1.1.0: + resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==} + requiresBuild: true + dev: false + optional: true + /jsc-android@250231.0.0: resolution: {integrity: sha512-rS46PvsjYmdmuz1OAWXY/1kCYG7pnf1TBqeTiOJr1iDz7s5DLxxC9n/ZMknLDxzYzNVfI7R95MH10emSSG1Wuw==} dev: false @@ -13653,6 +15625,10 @@ packages: engines: {node: '>=4'} hasBin: true + /json-bigint-patch@0.0.8: + resolution: {integrity: sha512-xa0LTQsyaq8awYyZyuUsporWisZFiyqzxGW8CKM3t7oouf0GFAKYJnqAm6e9NLNBQOCtOLvy614DEiRX/rPbnA==} + dev: false + /json-buffer@3.0.1: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} dev: true @@ -13663,7 +15639,12 @@ packages: /json-parse-even-better-errors@2.3.1: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} - dev: true + + /json-pointer@0.6.2: + resolution: {integrity: sha512-vLWcKbOaXlO+jvRy4qNd+TI1QUPZzfJj1tpJ3vAXDych5XJf93ftpUKe5pKCrzyIIwgBJcOcCVRUfqQP25afBw==} + dependencies: + foreach: 2.0.6 + dev: false /json-rpc-engine@6.1.0: resolution: {integrity: sha512-NEdLrtrq1jUZyfjkr9OCz9EzCNhnRyWtt1PAnvnhwy6e8XETS0Dtc+ZNCO2gvuAoKsIn2+vCSowXTYE4CkgnAQ==} @@ -13677,13 +15658,18 @@ packages: resolution: {integrity: sha512-RJ9YYNCkhVDBuP4zN5BBtYAzEl03yq/jIIsyif0JY9qyJuQQZNeDK7anAPKKlyEtLSj2s8h6hNh2F8zO5q7ScA==} dev: false + /json-schema-ref-resolver@1.0.1: + resolution: {integrity: sha512-EJAj1pgHc1hxF6vo2Z3s69fMjO1INq6eGHXZ8Z6wCQeldCuwxGK9Sxf4/cScGn3FZubCVUehfWtcDM/PLteCQw==} + dependencies: + fast-deep-equal: 3.1.3 + dev: false + /json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} dev: true /json-schema-traverse@1.0.0: resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} - dev: true /json-schema@0.4.0: resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} @@ -13840,6 +15826,12 @@ packages: type-check: 0.4.0 dev: true + /lie@3.1.1: + resolution: {integrity: sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==} + dependencies: + immediate: 3.0.6 + dev: false + /lighthouse-logger@1.4.2: resolution: {integrity: sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g==} dependencies: @@ -13939,7 +15931,6 @@ packages: /lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - dev: true /listhen@1.7.2: resolution: {integrity: sha512-7/HamOm5YD9Wb7CFgAZkKgVPA96WwhcTQoqtm2VTZGVbVVn3IWKRBTgrU7cchA3Q8k9iCsG8Osoi9GX4JsGM9g==} @@ -14009,6 +16000,12 @@ packages: pify: 4.0.1 strip-bom: 3.0.0 + /localforage@1.10.0: + resolution: {integrity: sha512-14/H1aX7hzBBmmh7sGPd+AOMkkIrHM3Z1PAyGgZigA1H1p5O5ANnMyWzvpAETtG68/dC4pC0ncy3+PPGzXZHPg==} + dependencies: + lie: 3.1.1 + dev: false + /locate-path@2.0.0: resolution: {integrity: sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==} engines: {node: '>=4'} @@ -14058,7 +16055,6 @@ packages: /lodash.get@4.4.2: resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} - dev: true /lodash.isequal@4.5.0: resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} @@ -14081,6 +16077,10 @@ packages: /lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + /lodash.mergewith@4.6.2: + resolution: {integrity: sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==} + dev: false + /lodash.pad@4.5.1: resolution: {integrity: sha512-mvUHifnLqM+03YNzeTBS1/Gr6JRFjd3rRx88FHWUvamVaT9k2O/kXha3yBSOwB9/DTQrSTLJNHvLBBt2FdX7Mg==} dev: true @@ -14109,6 +16109,10 @@ packages: resolution: {integrity: sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==} dev: false + /lodash.topath@4.5.2: + resolution: {integrity: sha512-1/W4dM+35DwvE/iEd1M9ekewOSTlpFekhw9mhAtrwjVqUr83/ilQiyAvmg4tVX7Unkcfl1KC+i9WdaT4B6aQcg==} + dev: false + /lodash.trim@4.5.1: resolution: {integrity: sha512-nJAlRl/K+eiOehWKDzoBVrSMhK0K3A3YQsUNXHQa5yIrKBAhsZgSu3KoAFoFT+mEgiyBHddZ0pRk1ITpIp90Wg==} dev: true @@ -14138,7 +16142,6 @@ packages: /lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - dev: true /log-symbols@3.0.0: resolution: {integrity: sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==} @@ -14159,7 +16162,7 @@ packages: hasBin: true dependencies: ansi-fragments: 0.2.1 - dayjs: 1.11.12 + dayjs: 1.11.13 yargs: 15.4.1 dev: false @@ -14197,6 +16200,12 @@ packages: lower-case: 1.1.4 dev: true + /lower-case-first@2.0.2: + resolution: {integrity: sha512-EVm/rR94FJTZi3zefZ82fLWab+GX14LJN4HrWBcuo6Evmsl9hEfnqxgcHCKb9q+mNf6EVdsjx/qucYFIIB84pg==} + dependencies: + tslib: 2.6.3 + dev: false + /lower-case@1.1.4: resolution: {integrity: sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA==} dev: true @@ -14205,7 +16214,6 @@ packages: resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} dependencies: tslib: 2.6.2 - dev: true /lowercase-keys@2.0.0: resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==} @@ -14220,6 +16228,11 @@ packages: /lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + /lru-cache@11.0.1: + resolution: {integrity: sha512-CgeuL5uom6j/ZVrg7G/+1IXqRY8JXX4Hghfy5YE0EhoYQWvndP1kufu58cmZLNIDKnRhZrXfdS9urVWx98AipQ==} + engines: {node: 20 || >=22} + dev: false + /lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} dependencies: @@ -14266,6 +16279,15 @@ packages: semver: 5.7.2 dev: false + /make-dir@3.1.0: + resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} + engines: {node: '>=8'} + requiresBuild: true + dependencies: + semver: 6.3.1 + dev: false + optional: true + /make-dir@4.0.0: resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} engines: {node: '>=10'} @@ -14277,12 +16299,39 @@ packages: resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} dev: true + /make-fetch-happen@13.0.1: + resolution: {integrity: sha512-cKTUFc/rbKUd/9meOvgrpJ2WrNzymt6jfRDdwg5UCnVzv9dTpEj9JS5m3wtziXVCjluIXyL8pcaukYqezIzZQA==} + engines: {node: ^16.14.0 || >=18.0.0} + requiresBuild: true + dependencies: + '@npmcli/agent': 2.2.2 + cacache: 18.0.4 + http-cache-semantics: 4.1.1 + is-lambda: 1.0.1 + minipass: 7.1.2 + minipass-fetch: 3.0.5 + minipass-flush: 1.0.5 + minipass-pipeline: 1.2.4 + negotiator: 0.6.3 + proc-log: 4.2.0 + promise-retry: 2.0.1 + ssri: 10.0.6 + transitivePeerDependencies: + - supports-color + dev: false + optional: true + /makeerror@1.0.12: resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} dependencies: tmpl: 1.0.5 dev: false + /map-cache@0.2.2: + resolution: {integrity: sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==} + engines: {node: '>=0.10.0'} + dev: false + /markdown-table@1.1.3: resolution: {integrity: sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==} dev: true @@ -14359,6 +16408,18 @@ packages: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} + /meros@1.3.0(@types/node@22.0.2): + resolution: {integrity: sha512-2BNGOimxEz5hmjUG2FwoxCt5HN7BXdaWyFqEwxPTrJzVdABtrL4TiHTcsWSFAxPQ/tOnEaQEJh3qWq71QRMY+w==} + engines: {node: '>=13'} + peerDependencies: + '@types/node': '>=13' + peerDependenciesMeta: + '@types/node': + optional: true + dependencies: + '@types/node': 22.0.2 + dev: false + /methods@1.1.2: resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} engines: {node: '>= 0.6'} @@ -14662,6 +16723,13 @@ packages: /minimalistic-crypto-utils@1.0.1: resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} + /minimatch@10.0.1: + resolution: {integrity: sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==} + engines: {node: 20 || >=22} + dependencies: + brace-expansion: 2.0.1 + dev: false + /minimatch@3.0.8: resolution: {integrity: sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==} dependencies: @@ -14705,11 +16773,59 @@ packages: engines: {node: '>=16 || 14 >=14.17'} dependencies: brace-expansion: 2.0.1 - dev: true /minimist@1.2.8: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + /minipass-collect@2.0.1: + resolution: {integrity: sha512-D7V8PO9oaz7PWGLbCACuI1qEOsq7UKfLotx/C0Aet43fCUB/wfQ7DYeq2oR/svFJGYDHPr38SHATeaj/ZoKHKw==} + engines: {node: '>=16 || 14 >=14.17'} + requiresBuild: true + dependencies: + minipass: 7.1.2 + dev: false + optional: true + + /minipass-fetch@3.0.5: + resolution: {integrity: sha512-2N8elDQAtSnFV0Dk7gt15KHsS0Fyz6CbYZ360h0WTYV1Ty46li3rAXVOQj1THMNLdmrD9Vt5pBPtWtVkpwGBqg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + requiresBuild: true + dependencies: + minipass: 7.1.2 + minipass-sized: 1.0.3 + minizlib: 2.1.2 + optionalDependencies: + encoding: 0.1.13 + dev: false + optional: true + + /minipass-flush@1.0.5: + resolution: {integrity: sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==} + engines: {node: '>= 8'} + requiresBuild: true + dependencies: + minipass: 3.3.6 + dev: false + optional: true + + /minipass-pipeline@1.2.4: + resolution: {integrity: sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==} + engines: {node: '>=8'} + requiresBuild: true + dependencies: + minipass: 3.3.6 + dev: false + optional: true + + /minipass-sized@1.0.3: + resolution: {integrity: sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==} + engines: {node: '>=8'} + requiresBuild: true + dependencies: + minipass: 3.3.6 + dev: false + optional: true + /minipass@2.9.0: resolution: {integrity: sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==} dependencies: @@ -14722,7 +16838,6 @@ packages: engines: {node: '>=8'} dependencies: yallist: 4.0.0 - dev: true /minipass@4.2.8: resolution: {integrity: sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==} @@ -14732,7 +16847,6 @@ packages: /minipass@5.0.0: resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==} engines: {node: '>=8'} - dev: true /minipass@7.0.4: resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==} @@ -14742,7 +16856,6 @@ packages: /minipass@7.1.2: resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} engines: {node: '>=16 || 14 >=14.17'} - dev: true /minizlib@1.3.3: resolution: {integrity: sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==} @@ -14756,7 +16869,6 @@ packages: dependencies: minipass: 3.3.6 yallist: 4.0.0 - dev: true /mipd@0.0.7(typescript@5.5.4): resolution: {integrity: sha512-aAPZPNDQ3uMTdKbuO2YmAw2TxLHO0moa4YKAyETM/DTj5FloZo+a+8tU+iv4GmW+sOxKLSRwcSFuczk+Cpt6fg==} @@ -14938,6 +17050,12 @@ packages: varint: 5.0.2 dev: true + /nan@2.18.0: + resolution: {integrity: sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==} + requiresBuild: true + dev: false + optional: true + /nano-base32@1.0.1: resolution: {integrity: sha512-sxEtoTqAPdjWVGv71Q17koMFGsOMSiHsIFEvzOM7cNp8BXB4AnEwmDabm5dorusJf/v1z7QxaZYxUorU9RKaAw==} dev: true @@ -15039,7 +17157,6 @@ packages: dependencies: lower-case: 2.0.2 tslib: 2.6.2 - dev: true /nocache@3.0.4: resolution: {integrity: sha512-WDD0bdg9mbq6F4mRxEYcPWwfA1vxd0mrvKOyxI7Xj/atfRHVeutzuWByG//jfm4uPzp0y4Kj051EORCBSQMycw==} @@ -15104,10 +17221,49 @@ packages: resolution: {integrity: sha512-OSs33Z9yWr148JZcbZd5WiAXhh/n9z8TxQcdMhIOlpN9AhWpLfvVFO73+m77bBABQMaY9XSvIa+qk0jlI7Gcaw==} hasBin: true + /node-gyp@10.0.1: + resolution: {integrity: sha512-gg3/bHehQfZivQVfqIyy8wTdSymF9yTyP4CJifK73imyNMU8AIGQE2pUa7dNWfmMeG9cDVF2eehiRMv0LC1iAg==} + engines: {node: ^16.14.0 || >=18.0.0} + hasBin: true + requiresBuild: true + dependencies: + env-paths: 2.2.1 + exponential-backoff: 3.1.1 + glob: 10.4.5 + graceful-fs: 4.2.11 + make-fetch-happen: 13.0.1 + nopt: 7.2.1 + proc-log: 3.0.0 + semver: 7.6.3 + tar: 6.2.1 + which: 4.0.0 + transitivePeerDependencies: + - supports-color + dev: false + optional: true + /node-int64@0.4.0: resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} dev: false + /node-libcurl@4.0.0: + resolution: {integrity: sha512-v+u+OgSq6ldvf8MrdjieAy/mv8WeTN94nrTomh62zhItF2HH0Ckin/QEqs8+35DWyYrE5nBM2480UtWVXktzbQ==} + engines: {node: '>=16.14'} + requiresBuild: true + dependencies: + '@mapbox/node-pre-gyp': 1.0.11 + env-paths: 2.2.0 + nan: 2.18.0 + node-gyp: 10.0.1 + npmlog: 7.0.1 + rimraf: 5.0.5 + tslib: 2.6.2 + transitivePeerDependencies: + - encoding + - supports-color + dev: false + optional: true + /node-releases@2.0.14: resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} @@ -15133,6 +17289,26 @@ packages: abbrev: 1.0.9 dev: true + /nopt@5.0.0: + resolution: {integrity: sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==} + engines: {node: '>=6'} + hasBin: true + requiresBuild: true + dependencies: + abbrev: 1.0.9 + dev: false + optional: true + + /nopt@7.2.1: + resolution: {integrity: sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + hasBin: true + requiresBuild: true + dependencies: + abbrev: 2.0.0 + dev: false + optional: true + /normalize-package-data@2.5.0: resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==} dependencies: @@ -15142,6 +17318,13 @@ packages: validate-npm-package-license: 3.0.4 dev: true + /normalize-path@2.1.1: + resolution: {integrity: sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==} + engines: {node: '>=0.10.0'} + dependencies: + remove-trailing-separator: 1.1.0 + dev: false + /normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} @@ -15163,6 +17346,31 @@ packages: dependencies: path-key: 4.0.0 + /npmlog@5.0.1: + resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==} + deprecated: This package is no longer supported. + requiresBuild: true + dependencies: + are-we-there-yet: 2.0.0 + console-control-strings: 1.1.0 + gauge: 3.0.2 + set-blocking: 2.0.0 + dev: false + optional: true + + /npmlog@7.0.1: + resolution: {integrity: sha512-uJ0YFk/mCQpLBt+bxN88AKd+gyqZvZDbtiNxk6Waqcj2aPRyfVx8ITawkyQynxUagInjdYT1+qj4NfA5KJJUxg==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + deprecated: This package is no longer supported. + requiresBuild: true + dependencies: + are-we-there-yet: 4.0.2 + console-control-strings: 1.1.0 + gauge: 5.0.2 + set-blocking: 2.0.0 + dev: false + optional: true + /nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} dependencies: @@ -15210,6 +17418,10 @@ packages: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} + /object-inspect@1.13.1: + resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} + dev: false + /object-inspect@1.13.2: resolution: {integrity: sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==} engines: {node: '>= 0.4'} @@ -15368,6 +17580,17 @@ packages: is-docker: 2.2.1 is-wsl: 2.2.0 + /optimism@0.18.0: + resolution: {integrity: sha512-tGn8+REwLRNFnb9WmcY5IfpOqeX2kpaYJ1s6Ae3mn12AeydLkR3j+jSCmVQFoXqU8D41PAJ1RG1rCRNWmNZVmQ==} + requiresBuild: true + dependencies: + '@wry/caches': 1.0.1 + '@wry/context': 0.7.4 + '@wry/trie': 0.4.3 + tslib: 2.6.3 + dev: false + optional: true + /optionator@0.8.3: resolution: {integrity: sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==} engines: {node: '>= 0.8.0'} @@ -15526,7 +17749,6 @@ packages: engines: {node: '>=10'} dependencies: aggregate-error: 3.1.0 - dev: true /p-try@1.0.0: resolution: {integrity: sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==} @@ -15539,7 +17761,6 @@ packages: /package-json-from-dist@1.0.0: resolution: {integrity: sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==} - dev: true /pako@1.0.11: resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} @@ -15551,12 +17772,18 @@ packages: no-case: 2.3.2 dev: true + /param-case@3.0.4: + resolution: {integrity: sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==} + dependencies: + dot-case: 3.0.4 + tslib: 2.6.3 + dev: false + /parent-module@1.0.1: resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} engines: {node: '>=6'} dependencies: callsites: 3.1.0 - dev: true /parse-cache-control@1.0.1: resolution: {integrity: sha512-60zvsJReQPX5/QP0Kzfd/VrpjScIQ7SHBW6bFCYfEP+fp0Eppr1SHhIO5nd1PjZtvclzSzES9D/p5nFJurwfWg==} @@ -15566,6 +17793,15 @@ packages: resolution: {integrity: sha512-z6t9dvSJYaPoQq7quMzdEagSFtpGu+utzHqqxmpVWNNZRIXnvqyCvn9XsTdh7c/w0Bqmdz3RB3YnRaKtpRtEXQ==} dev: true + /parse-filepath@1.0.2: + resolution: {integrity: sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q==} + engines: {node: '>=0.8'} + dependencies: + is-absolute: 1.0.0 + map-cache: 0.2.2 + path-root: 0.1.1 + dev: false + /parse-headers@2.0.5: resolution: {integrity: sha512-ft3iAoLOB/MlwbNXgzy43SWGP6sQki2jQvAyBg/zDFAgr9bfNWZIUj42Kw2eJIl8kEi4PbgE6U1Zau/HwI75HA==} dev: true @@ -15593,7 +17829,6 @@ packages: error-ex: 1.3.2 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 - dev: true /parse5-htmlparser2-tree-adapter@7.0.0: resolution: {integrity: sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g==} @@ -15618,6 +17853,13 @@ packages: upper-case-first: 1.1.2 dev: true + /pascal-case@3.1.2: + resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==} + dependencies: + no-case: 3.0.4 + tslib: 2.6.3 + dev: false + /password-prompt@1.1.3: resolution: {integrity: sha512-HkrjG2aJlvF0t2BMH0e2LB/EHf3Lcq3fNMzy4GYHcQblAvOl+QQji1Lx7WRBMqpVK8p+KR7bCg7oqAMXtdgqyw==} dependencies: @@ -15634,6 +17876,13 @@ packages: no-case: 2.3.2 dev: true + /path-case@3.0.4: + resolution: {integrity: sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==} + dependencies: + dot-case: 3.0.4 + tslib: 2.6.3 + dev: false + /path-exists@2.1.0: resolution: {integrity: sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ==} engines: {node: '>=0.10.0'} @@ -15664,6 +17913,18 @@ packages: /path-parse@1.0.7: resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + /path-root-regex@0.1.2: + resolution: {integrity: sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ==} + engines: {node: '>=0.10.0'} + dev: false + + /path-root@0.1.1: + resolution: {integrity: sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg==} + engines: {node: '>=0.10.0'} + dependencies: + path-root-regex: 0.1.2 + dev: false + /path-scurry@1.10.2: resolution: {integrity: sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==} engines: {node: '>=16 || 14 >=14.17'} @@ -15678,7 +17939,14 @@ packages: dependencies: lru-cache: 10.4.3 minipass: 7.1.2 - dev: true + + /path-scurry@2.0.0: + resolution: {integrity: sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==} + engines: {node: 20 || >=22} + dependencies: + lru-cache: 11.0.1 + minipass: 7.1.2 + dev: false /path-to-regexp@0.1.7: resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} @@ -15696,7 +17964,6 @@ packages: /path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} - dev: true /pathe@1.1.2: resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} @@ -16017,6 +18284,20 @@ packages: react-is: 18.3.1 dev: false + /proc-log@3.0.0: + resolution: {integrity: sha512-++Vn7NS4Xf9NacaU9Xq3URUuqZETPsf8L4j5/ckhaRYsfPeRyzGw+iDjFhV/Jr3uNmTvvddEJFWh5R1gRgUH8A==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + requiresBuild: true + dev: false + optional: true + + /proc-log@4.2.0: + resolution: {integrity: sha512-g8+OnU/L2v+wyiVK+D5fA34J7EH8jZ8DDlvwhRCMxmMj7UCBvxiO1mGeN+36JXIKF4zevU4kRBd8lVgG9vLelA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + requiresBuild: true + dev: false + optional: true + /process-nextick-args@2.0.1: resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} @@ -16029,6 +18310,22 @@ packages: engines: {node: '>= 0.6.0'} dev: true + /promise-retry@2.0.1: + resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==} + engines: {node: '>=10'} + requiresBuild: true + dependencies: + err-code: 2.0.3 + retry: 0.12.0 + dev: false + optional: true + + /promise@7.3.1: + resolution: {integrity: sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==} + dependencies: + asap: 2.0.6 + dev: false + /promise@8.3.0: resolution: {integrity: sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==} dependencies: @@ -16680,6 +18977,37 @@ packages: jsesc: 0.5.0 dev: false + /rehackt@0.1.0(@types/react@18.3.3)(react@18.3.1): + resolution: {integrity: sha512-7kRDOuLHB87D/JESKxQoRwv4DzbIdwkAGQ7p6QKGdVlY1IZheUnVhlk/4UZlNUVxdAXpyxikE3URsG067ybVzw==} + requiresBuild: true + peerDependencies: + '@types/react': '*' + react: '*' + peerDependenciesMeta: + '@types/react': + optional: true + react: + optional: true + dependencies: + '@types/react': 18.3.3 + react: 18.3.1 + dev: false + optional: true + + /relay-runtime@12.0.0: + resolution: {integrity: sha512-QU6JKr1tMsry22DXNy9Whsq5rmvwr3LSZiiWV/9+DFpuTWvp+WFhobWMc8TC4OjKFfNhEZy7mOiqUAn5atQtug==} + dependencies: + '@babel/runtime': 7.25.0 + fbjs: 3.0.5 + invariant: 2.2.4 + transitivePeerDependencies: + - encoding + dev: false + + /remove-trailing-separator@1.1.0: + resolution: {integrity: sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==} + dev: false + /req-cwd@2.0.0: resolution: {integrity: sha512-ueoIoLo1OfB6b05COxAA9UpeoscNpYyM+BqYlA7H6LVF4hKGPXQQSSaD2YmvDVJMkk4UDpAHIeU1zG53IqjvlQ==} engines: {node: '>=4'} @@ -16733,7 +19061,6 @@ packages: /require-from-string@2.0.2: resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} engines: {node: '>=0.10.0'} - dev: true /require-main-filename@1.0.1: resolution: {integrity: sha512-IqSUtOVP4ksd1C/ej5zeEh/BIP2ajqpn8c5x+q99gvcIG/Qf0cud5raVnE/Dwd0ua9TXYDoDc0RE5hBSdz22Ug==} @@ -16757,7 +19084,11 @@ packages: /resolve-from@4.0.0: resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} engines: {node: '>=4'} - dev: true + + /resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + dev: false /resolve-pkg-maps@1.0.0: resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} @@ -16796,6 +19127,13 @@ packages: supports-preserve-symlinks-flag: 1.0.0 dev: true + /response-iterator@0.2.6: + resolution: {integrity: sha512-pVzEEzrsg23Sh053rmDUvLSkGXluZio0qu8VT6ukrYuvtjVfCbDZH9d6PGXb8HZfzdNZt8feXv/jvUzlhRgLnw==} + engines: {node: '>=0.8'} + requiresBuild: true + dev: false + optional: true + /responselike@2.0.1: resolution: {integrity: sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==} dependencies: @@ -16813,10 +19151,21 @@ packages: resolution: {integrity: sha512-WKE0j11Pa0ZJI5YIk0nflGI7SQsfl2ljihVy7ogh7DeQSeYAUi0ubZ/yEueGtDfUPk6GH5LRw1hBdLq4IwUBWA==} dev: true + /retry@0.12.0: + resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==} + engines: {node: '>= 4'} + requiresBuild: true + dev: false + optional: true + /reusify@1.0.4: resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + /rfdc@1.4.1: + resolution: {integrity: sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==} + dev: false + /rimraf@2.6.3: resolution: {integrity: sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==} deprecated: Rimraf versions prior to v4 are no longer supported @@ -16840,6 +19189,25 @@ packages: dependencies: glob: 7.2.3 + /rimraf@5.0.5: + resolution: {integrity: sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==} + engines: {node: '>=14'} + hasBin: true + requiresBuild: true + dependencies: + glob: 10.4.5 + dev: false + optional: true + + /rimraf@6.0.1: + resolution: {integrity: sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==} + engines: {node: 20 || >=22} + hasBin: true + dependencies: + glob: 11.0.0 + package-json-from-dist: 1.0.0 + dev: false + /ripemd160-min@0.0.6: resolution: {integrity: sha512-+GcJgQivhs6S9qvLogusiTcS9kQUfgR75whKuy5jIhuiOfQuJ8fjqxV6EGD5duH1Y/FawFUMtMhyeq3Fbnib8A==} engines: {node: '>=8'} @@ -17121,6 +19489,14 @@ packages: upper-case-first: 1.1.2 dev: true + /sentence-case@3.0.4: + resolution: {integrity: sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==} + dependencies: + no-case: 3.0.4 + tslib: 2.6.3 + upper-case-first: 2.0.2 + dev: false + /serialize-error@2.1.0: resolution: {integrity: sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw==} engines: {node: '>=0.10.0'} @@ -17186,7 +19562,6 @@ packages: /setimmediate@1.0.5: resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} - dev: true /setprototypeof@1.2.0: resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} @@ -17292,6 +19667,10 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} + /signedsource@1.0.0: + resolution: {integrity: sha512-6+eerH9fEnNmi/hyM1DXcRK3pWdoMQtlkQ+ns0ntzunjKqp5i3sKCc80ym8Fib3iaYhdJUOPdhlJWj1tvge2Ww==} + dev: false + /simple-concat@1.0.1: resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} dev: true @@ -17335,6 +19714,13 @@ packages: is-fullwidth-code-point: 3.0.0 dev: true + /smart-buffer@4.2.0: + resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} + engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} + requiresBuild: true + dev: false + optional: true + /snake-case@2.1.0: resolution: {integrity: sha512-FMR5YoPFwOLuh4rRz92dywJjyKYZNLpMn1R5ujVpIYkbA9p01fq8RMg0FkO4M+Yobt4MjHeLTJVm5xFFBHSV2Q==} dependencies: @@ -17346,7 +19732,6 @@ packages: dependencies: dot-case: 3.0.4 tslib: 2.6.2 - dev: true /socket.io-client@4.7.5: resolution: {integrity: sha512-sJ/tqHOCe7Z50JCBCXrsY3I2k03iOiUe+tj1OmKeD2lXPiGH/RUCdTZFoqVyN7l1MnpIzPrGtLcijffmeouNlQ==} @@ -17372,6 +19757,29 @@ packages: - supports-color dev: false + /socks-proxy-agent@8.0.4: + resolution: {integrity: sha512-GNAq/eg8Udq2x0eNiFkr9gRg5bA7PXEWagQdeRX4cPSG+X/8V38v637gim9bjFptMk1QWsCTr0ttrJEiXbNnRw==} + engines: {node: '>= 14'} + requiresBuild: true + dependencies: + agent-base: 7.1.1 + debug: 4.3.6(supports-color@8.1.1) + socks: 2.8.3 + transitivePeerDependencies: + - supports-color + dev: false + optional: true + + /socks@2.8.3: + resolution: {integrity: sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==} + engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} + requiresBuild: true + dependencies: + ip-address: 9.0.5 + smart-buffer: 4.2.0 + dev: false + optional: true + /solc@0.4.26: resolution: {integrity: sha512-o+c6FpkiHd+HPjmjEVpQgH7fqZ14tJpXhho+/bQXlXbliLIS/xjXb42Vxh+qQY1WCSTMQ0+a5vR9vi0MfhU6mA==} hasBin: true @@ -17504,9 +19912,21 @@ packages: engines: {node: '>= 10.x'} dev: false + /sponge-case@1.0.1: + resolution: {integrity: sha512-dblb9Et4DAtiZ5YSUZHLl4XhH4uK80GhAZrVXdN4O2P4gQ40Wa5UIOPUHlA/nFd2PLblBZWUioLMMAVrgpoYcA==} + dependencies: + tslib: 2.6.3 + dev: false + /sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + /sprintf-js@1.1.3: + resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} + requiresBuild: true + dev: false + optional: true + /sshpk@1.18.0: resolution: {integrity: sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==} engines: {node: '>=0.10.0'} @@ -17523,6 +19943,15 @@ packages: tweetnacl: 0.14.5 dev: true + /ssri@10.0.6: + resolution: {integrity: sha512-MGrFH9Z4NP9Iyhqn16sDtBpRRNJ0Y2hNa6D65h736fVSaPCHr4DM4sWUNvVaSuC+0OBGhwsrydQwmgfg5LncqQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + requiresBuild: true + dependencies: + minipass: 7.1.2 + dev: false + optional: true + /stack-utils@2.0.6: resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} engines: {node: '>=10'} @@ -17628,7 +20057,6 @@ packages: eastasianwidth: 0.2.0 emoji-regex: 9.2.2 strip-ansi: 7.1.0 - dev: true /string.prototype.includes@2.0.0: resolution: {integrity: sha512-E34CkBgyeqNDcrbU76cDjL5JLcVrtSdYq0MEh/B10r17pRP4ciHLwTgnuLV8Ay6cgEMLkcBkFCKyFZ43YldYzg==} @@ -17734,7 +20162,6 @@ packages: engines: {node: '>=12'} dependencies: ansi-regex: 6.0.1 - dev: true /strip-bom@2.0.0: resolution: {integrity: sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g==} @@ -17872,6 +20299,12 @@ packages: upper-case: 1.1.3 dev: true + /swap-case@2.0.2: + resolution: {integrity: sha512-kc6S2YS/2yXbtkSMunBtKdah4VFETZ8Oh6ONSmSd9bRxhqTrtARUCBUiWXH3xVPpvR7tz2CSnkuXVE42EcGnMw==} + dependencies: + tslib: 2.6.3 + dev: false + /swarm-js@0.1.42: resolution: {integrity: sha512-BV7c/dVlA3R6ya1lMlSSNPLYrntt0LUq4YMgy3iwpCIc6rZnS5W2wUoctarZ5pXlpKtxDDf9hNziEkcfrxdhqQ==} dependencies: @@ -17892,6 +20325,13 @@ packages: - utf-8-validate dev: true + /symbol-observable@4.0.0: + resolution: {integrity: sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==} + engines: {node: '>=0.10'} + requiresBuild: true + dev: false + optional: true + /symbol-tree@3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} @@ -17990,7 +20430,6 @@ packages: minizlib: 2.1.2 mkdirp: 1.0.4 yallist: 4.0.0 - dev: true /temp-dir@2.0.0: resolution: {integrity: sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==} @@ -18084,6 +20523,11 @@ packages: retimer: 3.0.0 dev: true + /tiny-lru@11.2.11: + resolution: {integrity: sha512-27BIW0dIWTYYoWNnqSmoNMKe5WIbkXsc0xaCQHd3/3xT2XMuMJrzHdrO9QBFR14emBz1Bu0dOAs2sCBBrvgPQA==} + engines: {node: '>=12'} + dev: false + /tinybench@2.8.0: resolution: {integrity: sha512-1/eK7zUnIklz4JUUlL+658n58XO2hHLQfSk1Zf2LKieUjxidN16eKFEoDEfjHc3ohofSSqK3X5yO6VGb6iW8Lw==} dev: true @@ -18110,6 +20554,12 @@ packages: upper-case: 1.1.3 dev: true + /title-case@3.0.3: + resolution: {integrity: sha512-e1zGYRvbffpcHIrnuqT0Dh+gEJtDaxDSoG4JAIpq4oDFyooziLBIiYQv0GBT4FUAnUop5uZ1hiIAj7oAF6sOCA==} + dependencies: + tslib: 2.6.3 + dev: false + /tmp-promise@3.0.3: resolution: {integrity: sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==} dependencies: @@ -18219,6 +20669,15 @@ packages: object-path: 0.11.8 typescript: 5.5.4 + /ts-invariant@0.10.3: + resolution: {integrity: sha512-uivwYcQaxAucv1CzRp2n/QdYPo4ILf9VXgH19zEIjFx2EJufV16P0JtJVpYHy89DItG6Kwj2oIUjrcK5au+4tQ==} + engines: {node: '>=8'} + requiresBuild: true + dependencies: + tslib: 2.6.3 + dev: false + optional: true + /ts-morph@21.0.1: resolution: {integrity: sha512-dbDtVdEAncKctzrVZ+Nr7kHpHkv+0JDJb2MjjpBaj8bFeCkePU9rHfMklmhuLFnpeq/EJZk2IhStY6NzqgjOkg==} dependencies: @@ -18300,9 +20759,12 @@ packages: /tslib@1.14.1: resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + /tslib@2.4.1: + resolution: {integrity: sha512-tGyy4dAjRIEwI7BzsB0lynWgOpfqjUdq91XXAlIWD2OwKBH7oCl/GZG/HT4BOHrTlPMOASlMQ7veyTqpmRcrNA==} + dev: false + /tslib@2.6.2: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} - dev: true /tslib@2.6.3: resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==} @@ -18517,6 +20979,11 @@ packages: which-boxed-primitive: 1.0.2 dev: true + /unc-path-regex@0.1.2: + resolution: {integrity: sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==} + engines: {node: '>=0.10.0'} + dev: false + /uncrypto@0.1.3: resolution: {integrity: sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==} dev: false @@ -18580,6 +21047,24 @@ packages: engines: {node: '>=4'} dev: false + /unique-filename@3.0.0: + resolution: {integrity: sha512-afXhuC55wkAmZ0P18QsVE6kp8JaxrEokN2HGIoIVv2ijHQd419H0+6EigAFcIzXeMIkcIkNBpB3L/DXB3cTS/g==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + requiresBuild: true + dependencies: + unique-slug: 4.0.0 + dev: false + optional: true + + /unique-slug@4.0.0: + resolution: {integrity: sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + requiresBuild: true + dependencies: + imurmurhash: 0.1.4 + dev: false + optional: true + /universalify@0.1.2: resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} engines: {node: '>= 4.0.0'} @@ -18592,6 +21077,13 @@ packages: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} engines: {node: '>= 10.0.0'} + /unixify@1.0.0: + resolution: {integrity: sha512-6bc58dPYhCMHHuwxldQxO3RRNZ4eCogZ/st++0+fcC1nr0jiGUtAdBJ2qzmLQWSxbtz42pWt4QQMiZ9HvZf5cg==} + engines: {node: '>=0.10.0'} + dependencies: + normalize-path: 2.1.1 + dev: false + /unpipe@1.0.0: resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} engines: {node: '>= 0.8'} @@ -18701,10 +21193,22 @@ packages: upper-case: 1.1.3 dev: true + /upper-case-first@2.0.2: + resolution: {integrity: sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==} + dependencies: + tslib: 2.6.3 + dev: false + /upper-case@1.1.3: resolution: {integrity: sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA==} dev: true + /upper-case@2.0.2: + resolution: {integrity: sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==} + dependencies: + tslib: 2.6.3 + dev: false + /uqr@0.1.2: resolution: {integrity: sha512-MJu7ypHq6QasgF5YRTjqscSzQp/W11zoUk6kvmlH+fmWEs63Y0Eib13hYFwAzagRJcVY8WVnlV+eBDUGMJ5IbA==} dev: false @@ -18713,7 +21217,6 @@ packages: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} dependencies: punycode: 2.3.1 - dev: true /url-parse@1.5.10: resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} @@ -18725,6 +21228,10 @@ packages: resolution: {integrity: sha512-3AChu4NiXquPfeckE5R5cGdiHCMWJx1dwCWOmWIL4KHAziJNOFIYJlpGFeKDvwLPHovZRCxK3cYlwzqI9Vp+Gg==} dev: true + /urlpattern-polyfill@10.0.0: + resolution: {integrity: sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==} + dev: false + /urlpattern-polyfill@8.0.2: resolution: {integrity: sha512-Qp95D4TPJl1kC9SKigDcqgyM2VDVO4RiJc2d4qe5GrYm+zbIQCWWKAFaJNQ4BhdFeDGwBmAxqJBwWSJDb9T3BQ==} dev: true @@ -18859,6 +21366,11 @@ packages: use-sync-external-store: 1.2.0(react@18.3.1) dev: false + /value-or-promise@1.0.12: + resolution: {integrity: sha512-Z6Uz+TYwEqE7ZN50gwn+1LCVo9ZVrpxRPOhOLnncYkY1ZzOYtrX8Fwf/rFktZ8R5mJms6EZf5TqNOMeZmnPq9Q==} + engines: {node: '>=12'} + dev: false + /varint@5.0.2: resolution: {integrity: sha512-lKxKYG6H03yCZUpAGOPOsMcGxd1RHCu1iKvEHYDPmTyq2HueGhD73ssNBqqQWfvYs04G9iUFRvmAVLW20Jw6ow==} dev: true @@ -19940,7 +22452,6 @@ packages: hasBin: true dependencies: isexe: 3.1.1 - dev: true /why-is-node-running@2.3.0: resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} @@ -19951,6 +22462,14 @@ packages: stackback: 0.0.2 dev: true + /wide-align@1.1.5: + resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} + requiresBuild: true + dependencies: + string-width: 4.2.3 + dev: false + optional: true + /widest-line@3.1.0: resolution: {integrity: sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==} engines: {node: '>=8'} @@ -20017,7 +22536,6 @@ packages: ansi-styles: 6.2.1 string-width: 5.1.2 strip-ansi: 7.1.0 - dev: true /wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} @@ -20334,6 +22852,20 @@ packages: commander: 9.5.0 dev: true + /zen-observable-ts@1.2.5: + resolution: {integrity: sha512-QZWQekv6iB72Naeake9hS1KxHlotfRpe+WGNbNx5/ta+R3DNjVO2bswf63gXlWDcs+EMd7XY8HfVQyP1X6T4Zg==} + requiresBuild: true + dependencies: + zen-observable: 0.8.15 + dev: false + optional: true + + /zen-observable@0.8.15: + resolution: {integrity: sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==} + requiresBuild: true + dev: false + optional: true + /zod@3.23.8: resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} dev: true @@ -20365,3 +22897,11 @@ packages: optionalDependencies: '@types/fs-extra': 11.0.4 '@types/node': 22.0.2 + + github.com/uNetworking/uWebSockets.js/442087c0a01bf146acb7386910739ec81df06700: + resolution: {tarball: https://codeload.github.com/uNetworking/uWebSockets.js/tar.gz/442087c0a01bf146acb7386910739ec81df06700} + name: uWebSockets.js + version: 20.49.0 + requiresBuild: true + dev: false + optional: true diff --git a/subgraph/.gitignore b/subgraph/.gitignore index 52b33fb5..ec80919d 100644 --- a/subgraph/.gitignore +++ b/subgraph/.gitignore @@ -1,2 +1,3 @@ /build/ /generated/ +/networks-generated.json diff --git a/subgraph/cli/deploy-subgraph.ts b/subgraph/cli/deploy-subgraph.ts index 384fe25b..752c7cc9 100644 --- a/subgraph/cli/deploy-subgraph.ts +++ b/subgraph/cli/deploy-subgraph.ts @@ -1,9 +1,9 @@ -import YAML from "yaml"; import { $, echo, fs, minimist, path, question } from "zx"; - -const SUBGRAPH_PATH = path.join(__dirname, "../subgraph.yaml"); const LATEST_DEPLOYMENT_CONTEXT_PATH = path.join(__dirname, "../../contracts/deployment-context-latest.json"); +const NETWORKS_JSON_PATH = path.join(__dirname, "../networks.json"); +const GENERATED_NETWORKS_JSON_PATH = path.join(__dirname, "../networks-generated.json"); + const HELP = ` deploy-subgraph - deploy the Liquity v2 subgraph @@ -14,6 +14,7 @@ Arguments: NETWORK_PRESET A network preset, which is a shorthand for setting certain options. Options take precedence over network presets. Available presets: - local: Deploy to a local network + - sepolia: Deploy to Ethereum Sepolia - mainnet: Deploy to the Ethereum mainnet (not implemented) - liquity-testnet: Deploy to the Liquity v2 testnet (not implemented) @@ -25,6 +26,7 @@ Options: --help, -h Show this help message. --ipfs-node The IPFS node URL to use. --name The subgraph name to use. + --network The subgraph network to use. --version The subgraph version to use. `; @@ -41,24 +43,41 @@ const argv = minimist(process.argv.slice(2), { "graph-node", "ipfs-node", "name", + "network", "version", ], }); export async function main() { - const { networkPreset, options } = await parseArgs(); + const options = { + debug: argv["debug"], + help: argv["help"], + create: argv["create"], + graphNode: argv["graph-node"], + ipfsNode: argv["ipfs-node"], + name: argv["name"], + network: argv["network"], // subgraph network, not to be confused with the network preset + version: argv["version"], + }; + + const [networkPreset] = argv._; if (options.help) { echo`${HELP}`; process.exit(0); } - options.name ??= "liquity2/liquity2"; - // network preset: local if (networkPreset === "local") { + options.name ??= "liquity2/liquity2"; options.graphNode ??= "http://localhost:8020/"; options.ipfsNode ??= "http://localhost:5001/"; + options.network ??= "local"; + } + + if (networkPreset === "sepolia") { + options.name ??= "liquity2"; + options.network ??= "sepolia"; } // network preset: liquity-testnet @@ -71,41 +90,45 @@ export async function main() { // TODO: implement } - // handle missing options - if (!options.graphNode) { - throw new Error("--graph-node is required"); - } + const isLocal = options.network === "local"; + if (isLocal) options.network = "mainnet"; + if (!options.name) { throw new Error("--name is required"); } - if (!options.version) { - throw new Error("--version is required"); + if (!options.network) { + throw new Error("--network is required"); } - if (!options.ipfsNode) { + if (!options.graphNode && !options.network) { + throw new Error("--graph-node is required"); + } + if (!options.ipfsNode && !options.network) { throw new Error("--ipfs-node is required"); } - const graphCreateCommand: null | string[] = !options.create ? null : [ + const graphBuildCommand: string[] = [ "graph", - "create", - "--node", - options.graphNode, - options.name, + "build", + "--network", + options.network, ]; - const graphDeployCommand: string[] = [ + const graphCreateCommand: null | string[] = !options.create ? null : [ "graph", - "deploy", - "--node", - options.graphNode, - "--ipfs", - options.ipfsNode, + "create", + ...(options.graphNode ? ["--node", options.graphNode] : []), options.name, - "--version-label", - options.version, ]; - await updateDeclarationWithLatestBoldToken(); + const graphDeployCommand: string[] = ["graph", "deploy"]; + if (options.graphNode) graphDeployCommand.push("--node", options.graphNode); + if (options.network) graphDeployCommand.push("--network", options.network); + if (options.version) graphDeployCommand.push("--version-label", options.version); + if (options.ipfsNode) graphDeployCommand.push("--ipfs", options.ipfsNode); + graphDeployCommand.push(options.name); + + await updateNetworksWithLocalBoldToken(); + await generateNetworksJson(isLocal); echo` Deploying subgraph: @@ -120,6 +143,8 @@ Deploying subgraph: $.verbose = options.debug; + await $`pnpm ${graphBuildCommand}`; + if (graphCreateCommand) { await $`pnpm ${graphCreateCommand}`; } @@ -130,33 +155,32 @@ Deploying subgraph: echo(""); } -async function parseArgs() { - const options = { - debug: argv["debug"], - help: argv["help"], - create: argv["create"], - graphNode: argv["graph-node"], - ipfsNode: argv["ipfs-node"], - name: argv["name"], - version: argv["version"], - }; - - const [networkPreset] = argv._; - - return { options, networkPreset }; +async function generateNetworksJson(isLocal = false) { + const networksJson = JSON.parse(await fs.readFile(NETWORKS_JSON_PATH, "utf8")); + return fs.writeFile( + GENERATED_NETWORKS_JSON_PATH, + JSON.stringify( + { + ...networksJson, + mainnet: isLocal ? networksJson.local : networksJson.mainnet, + }, + null, + 2, + ), + ); } -async function updateDeclarationWithLatestBoldToken() { - const declaration = subgraphDeclaration(); +async function updateNetworksWithLocalBoldToken() { + const networksJson = JSON.parse(await fs.readFile(NETWORKS_JSON_PATH, "utf8")); const latestDeploymentContext = getLatestDeploymentContext(); const deployedAddress = latestDeploymentContext?.protocolContracts.BoldToken; - if (!deployedAddress || (declaration.boldTokenAddress === deployedAddress)) { + if (!deployedAddress || (networksJson.local.BoldToken.address === deployedAddress)) { return; } const answer = await question( - `\nNew BoldToken detected (${deployedAddress}). Update subgraph.yaml? [Y/n] `, + `\nNew BoldToken detected (${deployedAddress}) for local network. Update networks.json? [Y/n] `, ); const confirmed = answer === "" || answer.toLowerCase() === "y" || answer.toLowerCase() === "yes"; @@ -165,31 +189,11 @@ async function updateDeclarationWithLatestBoldToken() { return; } - declaration.updateBoldTokenAddress(deployedAddress); - console.log(""); - console.log("Subgraph declaration updated with CollateralRegistry:", deployedAddress); -} + networksJson.local.BoldToken.address = deployedAddress; + await fs.writeFile(NETWORKS_JSON_PATH, JSON.stringify(networksJson, null, 2)); -function subgraphDeclaration() { - const declaration = YAML.parse(fs.readFileSync(SUBGRAPH_PATH, "utf8")); - const boldToken = declaration.dataSources.find((ds: any) => ds.name === "BoldToken"); - return { - boldTokenAddress: boldToken.source.address, - updateBoldTokenAddress: (address: string) => { - const updatedDeclaration = { - ...declaration, - dataSources: declaration.dataSources.map((ds: any) => ( - ds.name === "BoldToken" - ? { ...ds, source: { ...ds.source, address } } - : ds - )), - }; - fs.writeFileSync( - SUBGRAPH_PATH, - YAML.stringify(updatedDeclaration, { lineWidth: 120 }), - ); - }, - }; + console.log(""); + console.log("networks.json updated with local BoldToken:", deployedAddress); } function getLatestDeploymentContext() { @@ -199,3 +203,23 @@ function getLatestDeploymentContext() { return null; } } + +declare module "zx" { + type MinimistOptions = { + string?: readonly S[]; + boolean?: readonly B[]; + alias?: { [key: string]: B | S }; + default?: { [key in B | S]?: boolean | string }; + }; + + type MinimistResult = + & { _: string[] } + & { [K in B]: boolean } + & { [K in S]: string | undefined } + & { [K in string]: boolean | string | string[] }; + + function minimist( + args: string[], + options?: MinimistOptions, + ): MinimistResult; +} diff --git a/subgraph/networks.json b/subgraph/networks.json new file mode 100644 index 00000000..ab044a37 --- /dev/null +++ b/subgraph/networks.json @@ -0,0 +1,19 @@ +{ + "local": { + "BoldToken": { + "address": "0x6112a1c20272a6fcc06abb8e8118e494993041ba" + } + }, + "mainnet": { + "BoldToken": { + "address": "0x0000000000000000000000000000000000000000", + "startBlock": 0 + } + }, + "sepolia": { + "BoldToken": { + "address": "0x8b6142b0469bad2a695a25caa2d40778e06ada10", + "startBlock": 6631293 + } + } +} diff --git a/subgraph/package.json b/subgraph/package.json index 73d4baa9..2a2a30db 100644 --- a/subgraph/package.json +++ b/subgraph/package.json @@ -10,7 +10,6 @@ "dependencies": { "@graphprotocol/graph-ts": "^0.35.1", "tsx": "^4.16.5", - "yaml": "^2.5.0", "zx": "^8.1.4" } } diff --git a/subgraph/schema.graphql b/subgraph/schema.graphql index 64c029cd..478b79aa 100644 --- a/subgraph/schema.graphql +++ b/subgraph/schema.graphql @@ -1,5 +1,6 @@ type Collateral @entity { id: ID! + collIndex: Int! token: Token! minCollRatio: BigInt! troves: [Trove!]! @derivedFrom(field: "collateral") @@ -36,6 +37,7 @@ type InterestRateBracket @entity { type Trove @entity { id: ID! + troveId: String! borrower: Bytes! debt: BigInt! deposit: BigInt! @@ -45,3 +47,9 @@ type Trove @entity { closedAt: BigInt collateral: Collateral! } + +type BorrowerInfo @entity { + id: ID! + troves: Int! + trovesByCollateral: [Int!]! +} diff --git a/subgraph/src/BoldToken.mapping.ts b/subgraph/src/BoldToken.mapping.ts index a5184be8..b8121b16 100644 --- a/subgraph/src/BoldToken.mapping.ts +++ b/subgraph/src/BoldToken.mapping.ts @@ -10,11 +10,14 @@ import { Collateral, CollateralAddresses, Token } from "../generated/schema"; import { TroveManager as TroveManagerTemplate } from "../generated/templates"; function addCollateral( + collIndex: i32, + totalCollaterals: i32, tokenAddress: Address, troveManagerAddress: Address, ): void { let id = tokenAddress.toHexString(); let collateral = new Collateral(id); + collateral.collIndex = collIndex; collateral.token = id; collateral.totalDebt = BigInt.fromI32(0); collateral.totalDeposited = BigInt.fromI32(0); @@ -44,6 +47,7 @@ function addCollateral( token.save(); let context = new DataSourceContext(); + context.setI32("totalCollaterals", totalCollaterals); context.setBytes("address:borrowerOperations", addresses.borrowerOperations); context.setBytes("address:sortedTroves", addresses.sortedTroves); context.setBytes("address:stabilityPool", addresses.stabilityPool); @@ -56,11 +60,11 @@ function addCollateral( export function handleCollateralRegistryAddressChanged(event: CollateralRegistryAddressChangedEvent): void { let registry = CollateralRegistry.bind(event.params._newCollateralRegistryAddress); - let colls = registry.totalCollaterals().toI32(); + let totalCollaterals = registry.totalCollaterals().toI32(); - for (let i = 0; i < colls; i++) { - let tokenAddress = Address.fromBytes(registry.getToken(BigInt.fromI32(i))); - let troveManagerAddress = Address.fromBytes(registry.getTroveManager(BigInt.fromI32(i))); + for (let index = 0; index < totalCollaterals; index++) { + let tokenAddress = Address.fromBytes(registry.getToken(BigInt.fromI32(index))); + let troveManagerAddress = Address.fromBytes(registry.getTroveManager(BigInt.fromI32(index))); if (tokenAddress.toHex() === Address.zero().toHex() || troveManagerAddress.toHex() === Address.zero().toHex()) { break; @@ -68,7 +72,12 @@ export function handleCollateralRegistryAddressChanged(event: CollateralRegistry // we use the token address as the id for the collateral if (!Collateral.load(tokenAddress.toHexString())) { - addCollateral(tokenAddress, troveManagerAddress); + addCollateral( + index, + totalCollaterals, + tokenAddress, + troveManagerAddress, + ); } } } diff --git a/subgraph/src/TroveManager.mapping.ts b/subgraph/src/TroveManager.mapping.ts index b80269df..2f7ff9f5 100644 --- a/subgraph/src/TroveManager.mapping.ts +++ b/subgraph/src/TroveManager.mapping.ts @@ -1,5 +1,5 @@ import { Address, BigInt, dataSource } from "@graphprotocol/graph-ts"; -import { Collateral, InterestRateBracket, Trove } from "../generated/schema"; +import { BorrowerInfo, Collateral, InterestRateBracket, Trove } from "../generated/schema"; import { TroveNFT } from "../generated/templates/TroveManager/TroveNFT"; import { TroveOperation as TroveOperationEvent, @@ -21,12 +21,24 @@ function floorToDecimals(value: BigInt, decimals: u8): BigInt { return value.div(factor).times(factor); } +// prefix an id with the collateral index +function getCollPrefixId(): string { + let collId = dataSource.context().getBytes("address:token").toHexString(); + let collateral = Collateral.load(collId); + if (!collateral) { + throw new Error("Collateral not found: " + collId); + } + return collateral.collIndex.toString() + ":"; +} + export function handleTroveOperation(event: TroveOperationEvent): void { - let id = event.params._troveId; - let trove = Trove.load(id.toHex()); + let troveId = event.params._troveId; + + let collPrefixId = getCollPrefixId(); + let trove = Trove.load(collPrefixId + troveId.toHexString()); if (!trove) { - return; + throw new Error("Trove not found: " + collPrefixId + troveId.toHexString()); } if (event.params._operation === OP_CLOSE_TROVE) { @@ -34,7 +46,7 @@ export function handleTroveOperation(event: TroveOperationEvent): void { // update rate bracket let rateFloored = floorToDecimals(event.params._annualInterestRate, 3); - let rateBracket = InterestRateBracket.load(rateFloored.toString()); + let rateBracket = InterestRateBracket.load(collPrefixId + rateFloored.toString()); if (rateBracket) { rateBracket.totalDebt = rateBracket.totalDebt.minus(trove.debt); rateBracket.totalTroves = rateBracket.totalTroves - 1; @@ -47,22 +59,37 @@ export function handleTroveOperation(event: TroveOperationEvent): void { } } -function loadOrCreateInterestRateBracket(rateFloored: BigInt): InterestRateBracket { - let rateBracket = InterestRateBracket.load(rateFloored.toString()); +function loadOrCreateInterestRateBracket( + collPrefixId: string, + rateFloored: BigInt, +): InterestRateBracket { + let rateBracket = InterestRateBracket.load(collPrefixId + rateFloored.toString()); + if (!rateBracket) { - rateBracket = new InterestRateBracket(rateFloored.toString()); + rateBracket = new InterestRateBracket(collPrefixId + rateFloored.toString()); rateBracket.rate = rateFloored; rateBracket.totalDebt = BigInt.fromI32(0); rateBracket.totalTroves = 0; + rateBracket.save(); } - rateBracket.save(); + return rateBracket; } export function handleTroveUpdated(event: TroveUpdatedEvent): void { - let id = event.params._troveId; - let trove = Trove.load(id.toHex()); + let troveId = event.params._troveId; + let context = dataSource.context(); + let collId = context.getBytes("address:token").toHexString(); + let collateral = Collateral.load(collId); + + // should never happen + if (!collateral) { + return; + } + + let collPrefixId = getCollPrefixId(); + let trove = Trove.load(collPrefixId + troveId.toHexString()); // previous & new rates, floored to the nearest 0.1% (rate brackets) let prevRateFloored = trove ? floorToDecimals(trove.interestRate, 3) : null; @@ -74,29 +101,44 @@ export function handleTroveUpdated(event: TroveUpdatedEvent): void { let prevDebt = trove ? trove.debt : BigInt.fromI32(0); let debt = event.params._debt; - let collId = context.getBytes("address:token").toHexString(); - let collateral = Collateral.load(collId); - - // should never happen - if (!collateral) { - return; - } - collateral.totalDeposited = collateral.totalDeposited.minus(prevDeposit).plus(deposit); collateral.totalDebt = collateral.totalDebt.minus(prevDebt).plus(debt); collateral.save(); - // create trove if it doesn't exist + // create trove if needed if (!trove) { - trove = new Trove(id.toHex()); - trove.borrower = TroveNFT.bind(Address.fromBytes(context.getBytes("address:troveNft"))).ownerOf(id); + let troveNftAddress = context.getBytes("address:troveNft"); + let borrowerAddress = TroveNFT.bind(Address.fromBytes(troveNftAddress)).ownerOf(troveId); + + // create borrower if needed + let borrowerInfo = BorrowerInfo.load(borrowerAddress.toHexString()); + if (!borrowerInfo) { + borrowerInfo = new BorrowerInfo(borrowerAddress.toHexString()); + borrowerInfo.troves = 0; + + let totalCollaterals = context.getI32("totalCollaterals"); + borrowerInfo.trovesByCollateral = (new Array(totalCollaterals)).fill(0); + borrowerInfo.save(); + } + + trove = new Trove(collPrefixId + troveId.toHexString()); + trove.troveId = troveId.toHexString(); trove.createdAt = event.block.timestamp; + trove.borrower = borrowerAddress; + + borrowerInfo.troves += 1; + + let trovesByColl = borrowerInfo.trovesByCollateral; + trovesByColl[collateral.collIndex] += 1; + borrowerInfo.trovesByCollateral = trovesByColl; + + borrowerInfo.save(); } // update interest rate brackets - let rateBracket = loadOrCreateInterestRateBracket(rateFloored); + let rateBracket = loadOrCreateInterestRateBracket(collPrefixId, rateFloored); if (!prevRateFloored || rateFloored.notEqual(prevRateFloored)) { - let prevRateBracket = prevRateFloored ? InterestRateBracket.load(prevRateFloored.toString()) : null; + let prevRateBracket = prevRateFloored ? InterestRateBracket.load(collPrefixId + prevRateFloored.toString()) : null; if (prevRateBracket) { prevRateBracket.totalDebt = prevRateBracket.totalDebt.minus(trove.debt); prevRateBracket.totalTroves = prevRateBracket.totalTroves - 1; diff --git a/subgraph/subgraph.yaml b/subgraph/subgraph.yaml index 95279d3a..6cb73a10 100644 --- a/subgraph/subgraph.yaml +++ b/subgraph/subgraph.yaml @@ -1,13 +1,15 @@ specVersion: 1.2.0 +indexerHints: + prune: auto schema: file: ./schema.graphql dataSources: - - name: BoldToken - kind: ethereum/contract - network: mainnet + - kind: ethereum/contract + name: BoldToken source: - address: "0x2705179df91e93d2be0f3b56454002f52e27ef87" abi: BoldToken + address: "0x8b6142b0469bad2a695a25caa2d40778e06ada10" + startBlock: 6631293 mapping: kind: ethereum/events apiVersion: 0.0.9 @@ -31,10 +33,11 @@ dataSources: - event: CollateralRegistryAddressChanged(address) handler: handleCollateralRegistryAddressChanged file: ./src/BoldToken.mapping.ts + network: sepolia templates: - name: TroveManager kind: ethereum/contract - network: mainnet + network: sepolia source: abi: TroveManager mapping: @@ -50,7 +53,9 @@ templates: - name: TroveNFT file: ../contracts/out/TroveNFT.sol/TroveNFT.json eventHandlers: - - event: TroveOperation(indexed uint256,uint8,uint256,uint256,uint256,int256,uint256,int256) + - event: TroveOperation(indexed + uint256,uint8,uint256,uint256,uint256,int256,uint256,int256) handler: handleTroveOperation - - event: TroveUpdated(indexed uint256,uint256,uint256,uint256,uint256,uint256,uint256) + - event: TroveUpdated(indexed + uint256,uint256,uint256,uint256,uint256,uint256,uint256) handler: handleTroveUpdated