diff --git a/frontend/app/.env b/frontend/app/.env index 258be471a..e9d972788 100644 --- a/frontend/app/.env +++ b/frontend/app/.env @@ -34,86 +34,86 @@ NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID=fd37755b4d4f8a59a1a064af3782ded4 # Ethereum (mainnet) # ###################### -NEXT_PUBLIC_CHAIN_BLOCK_EXPLORER=Etherscan|https://etherscan.io -NEXT_PUBLIC_CHAIN_CONTRACT_MULTICALL=0xca11bde05977b3631167028862be2a173976ca11 -NEXT_PUBLIC_CHAIN_CURRENCY=Ether|ETH|18 -NEXT_PUBLIC_CHAIN_ID=1 -NEXT_PUBLIC_CHAIN_NAME=Ethereum -NEXT_PUBLIC_CHAIN_RPC_URL=https://cloudflare-eth.com -NEXT_PUBLIC_DELEGATE_AUTO=0x0000000000000000000000000000000000000000 -NEXT_PUBLIC_KNOWN_INITIATIVES_URL=https://api.liquity.org/v2/known-initiatives/ethereum.json -NEXT_PUBLIC_LIQUITY_STATS_URL=https://api.liquity.org/v2/ethereum.json -NEXT_PUBLIC_LIQUITY_GOVERNANCE_URL=https://api.liquity.org/v2/governance -NEXT_PUBLIC_SAFE_API_URL=https://safe-transaction-mainnet.safe.global/api -NEXT_PUBLIC_SBOLD=0x50Bd66D59911F5e086Ec87aE43C811e0D059DD11 -NEXT_PUBLIC_TROVE_EXPLORER_0=DeFi Explore|https://liquityv2.defiexplore.com/trove/{branch}/{troveId} -NEXT_PUBLIC_TROVE_EXPLORER_1=Rails|https://rails.finance/explorer/trove/{troveId}/{branch} - -# Uncomment one of these: -# -# Create an account on https://beta.graphseer.com/ and insert your API key: -# NEXT_PUBLIC_SUBGRAPH_URL=https://graph-gateway.graphops.xyz/api/ad592eaf307cf800835a228774674bd0/subgraphs/id/6bg574MHrEZXopJDYTu7S7TAvJKEMsV111gpKLM7ZCA7 -# -# Or use a subgraph API key: -NEXT_PUBLIC_SUBGRAPH_URL=https://gateway.thegraph.com/api/e6637aa857aed5275df47cc1bea63550/subgraphs/id/6bg574MHrEZXopJDYTu7S7TAvJKEMsV111gpKLM7ZCA7 - -NEXT_PUBLIC_COLL_0_TOKEN_ID=ETH -NEXT_PUBLIC_COLL_1_TOKEN_ID=WSTETH -NEXT_PUBLIC_COLL_2_TOKEN_ID=RETH - -# Use the following format for the IC strategies: -# NEXT_PUBLIC_COLL_{index}_IC_STRATEGIES={strategy_name}:{address},{strategy_name}:{address},… -# NEXT_PUBLIC_COLL_0_IC_STRATEGIES= -# NEXT_PUBLIC_COLL_1_IC_STRATEGIES= -# NEXT_PUBLIC_COLL_2_IC_STRATEGIES= - -NEXT_PUBLIC_COLL_0_CONTRACT_ACTIVE_POOL=0xeb5a8c825582965f1d84606e078620a84ab16afe -NEXT_PUBLIC_COLL_0_CONTRACT_ADDRESSES_REGISTRY=0x20f7c9ad66983f6523a0881d0f82406541417526 -NEXT_PUBLIC_COLL_0_CONTRACT_BORROWER_OPERATIONS=0x372abd1810eaf23cb9d941bbe7596dfb2c46bc65 -NEXT_PUBLIC_COLL_0_CONTRACT_COLL_SURPLUS_POOL=0xedbe2509e502c0320d2e7f8b6746a49b4b50e2bf -NEXT_PUBLIC_COLL_0_CONTRACT_COLL_TOKEN=0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2 -NEXT_PUBLIC_COLL_0_CONTRACT_DEFAULT_POOL=0xd4558240d50c2e219a21c9d25afd513bb6e5b1a0 -NEXT_PUBLIC_COLL_0_CONTRACT_LEVERAGE_ZAPPER=0xdccbd7a365aee086aa3b4ede8afe895b20770ae3 -NEXT_PUBLIC_COLL_0_CONTRACT_PRICE_FEED=0xcc5f8102eb670c89a4a3c567c13851260303c24f -NEXT_PUBLIC_COLL_0_CONTRACT_SORTED_TROVES=0xa25269e41bd072513849f2e64ad221e84f3063f4 -NEXT_PUBLIC_COLL_0_CONTRACT_STABILITY_POOL=0x5721cbbd64fc7ae3ef44a0a3f9a790a9264cf9bf -NEXT_PUBLIC_COLL_0_CONTRACT_TROVE_MANAGER=0x7bcb64b2c9206a5b699ed43363f6f98d4776cf5a -NEXT_PUBLIC_COLL_0_CONTRACT_TROVE_NFT=0x1a0fc0b843afd9140267d25d4e575cb37a838013 -NEXT_PUBLIC_COLL_1_CONTRACT_ACTIVE_POOL=0x531a8f99c70d6a56a7cee02d6b4281650d7919a0 -NEXT_PUBLIC_COLL_1_CONTRACT_ADDRESSES_REGISTRY=0x8d733f7ea7c23cbea7c613b6ebd845d46d3aac54 -NEXT_PUBLIC_COLL_1_CONTRACT_BORROWER_OPERATIONS=0xa741a32f9dcfe6adba088fd0f97e90742d7d5da3 -NEXT_PUBLIC_COLL_1_CONTRACT_COLL_SURPLUS_POOL=0x36e6cbdf68f64cf00fc3a6c634a25be32dd0a235 -NEXT_PUBLIC_COLL_1_CONTRACT_COLL_TOKEN=0x7f39c581f595b53c5cb19bd0b3f8da6c935e2ca0 -NEXT_PUBLIC_COLL_1_CONTRACT_DEFAULT_POOL=0xd796e1648526400386cc4d12fa05e5f11e6a22a1 -NEXT_PUBLIC_COLL_1_CONTRACT_LEVERAGE_ZAPPER=0xe85230de04147c4ea363b21cdb801c1c19df0a56 -NEXT_PUBLIC_COLL_1_CONTRACT_PRICE_FEED=0xe7aa2ba9e086a379d3beb224098bc634a46e314e -NEXT_PUBLIC_COLL_1_CONTRACT_SORTED_TROVES=0x84eb85a8c25049255614f0536bea8f31682e86f1 -NEXT_PUBLIC_COLL_1_CONTRACT_STABILITY_POOL=0x9502b7c397e9aa22fe9db7ef7daf21cd2aebe56b -NEXT_PUBLIC_COLL_1_CONTRACT_TROVE_MANAGER=0xa2895d6a3bf110561dfe4b71ca539d84e1928b22 -NEXT_PUBLIC_COLL_1_CONTRACT_TROVE_NFT=0x857aecebf75f1012dc18e15020c97096aea31b04 -NEXT_PUBLIC_COLL_2_CONTRACT_ACTIVE_POOL=0x9074d72cc82dad1e13e454755aa8f144c479532f -NEXT_PUBLIC_COLL_2_CONTRACT_ADDRESSES_REGISTRY=0x6106046f031a22713697e04c08b330ddaf3e8789 -NEXT_PUBLIC_COLL_2_CONTRACT_BORROWER_OPERATIONS=0xe8119fc02953b27a1b48d2573855738485a17329 -NEXT_PUBLIC_COLL_2_CONTRACT_COLL_SURPLUS_POOL=0xba4a2bd8b76df84cac98eba3f4b967d8423192bf -NEXT_PUBLIC_COLL_2_CONTRACT_COLL_TOKEN=0xae78736cd615f374d3085123a210448e74fc6393 -NEXT_PUBLIC_COLL_2_CONTRACT_DEFAULT_POOL=0x5cc5cefd034fdc4728d487a72ca58a410cddcd6b -NEXT_PUBLIC_COLL_2_CONTRACT_LEVERAGE_ZAPPER=0x75036b1d6de5665c60f5c33bb4a64e8e123211a2 -NEXT_PUBLIC_COLL_2_CONTRACT_PRICE_FEED=0x34f1e9c7dcc279ec70d3c4488eb2d80fba8b7b2b -NEXT_PUBLIC_COLL_2_CONTRACT_SORTED_TROVES=0x14d8d8011df2b396ed2bbc4959bb73250324f386 -NEXT_PUBLIC_COLL_2_CONTRACT_STABILITY_POOL=0xd442e41019b7f5c4dd78f50dc03726c446148695 -NEXT_PUBLIC_COLL_2_CONTRACT_TROVE_MANAGER=0xb2b2abeb5c357a234363ff5d180912d319e3e19e -NEXT_PUBLIC_COLL_2_CONTRACT_TROVE_NFT=0x7ae430e25b67f19b431e1d1dc048a5bcf24c0873 -NEXT_PUBLIC_CONTRACT_BOLD_TOKEN=0x6440f144b7e50d6a8439336510312d2f54beb01d -NEXT_PUBLIC_CONTRACT_COLLATERAL_REGISTRY=0xf949982b91c8c61e952b3ba942cbbfaef5386684 -NEXT_PUBLIC_CONTRACT_DEBT_IN_FRONT_HELPER=0x4bb5e28fdb12891369b560f2fab3c032600677c6 -NEXT_PUBLIC_CONTRACT_EXCHANGE_HELPERS=0x2f60bab0072abec7058017f48d7256ec288c8686 -NEXT_PUBLIC_CONTRACT_GOVERNANCE=0x807def5e7d057df05c796f4bc75c3fe82bd6eee1 -NEXT_PUBLIC_CONTRACT_HINT_HELPERS=0xf0cae19c96e572234398d6665cc1147a16cbe657 -NEXT_PUBLIC_CONTRACT_LQTY_STAKING=0x4f9fbb3f1e99b56e0fe2892e623ed36a76fc605d -NEXT_PUBLIC_CONTRACT_LQTY_TOKEN=0x6dea81c8171d0ba574754ef6f8b412f2ed88c54d -NEXT_PUBLIC_CONTRACT_LUSD_TOKEN=0x5f98805a4e8be255a32880fdec7f6728c6568ba0 -NEXT_PUBLIC_CONTRACT_MULTI_TROVE_GETTER=0xfa61db085510c64b83056db3a7acf3b6f631d235 -NEXT_PUBLIC_CONTRACT_WETH=0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2 +# NEXT_PUBLIC_CHAIN_BLOCK_EXPLORER=Etherscan|https://etherscan.io +# NEXT_PUBLIC_CHAIN_CONTRACT_MULTICALL=0xca11bde05977b3631167028862be2a173976ca11 +# NEXT_PUBLIC_CHAIN_CURRENCY=Ether|ETH|18 +# NEXT_PUBLIC_CHAIN_ID=1 +# NEXT_PUBLIC_CHAIN_NAME=Ethereum +# NEXT_PUBLIC_CHAIN_RPC_URL=https://cloudflare-eth.com +# NEXT_PUBLIC_DELEGATE_AUTO=0x0000000000000000000000000000000000000000 +# NEXT_PUBLIC_KNOWN_INITIATIVES_URL=https://api.liquity.org/v2/known-initiatives/ethereum.json +# NEXT_PUBLIC_LIQUITY_STATS_URL=https://api.liquity.org/v2/ethereum.json +# NEXT_PUBLIC_LIQUITY_GOVERNANCE_URL=https://api.liquity.org/v2/governance +# NEXT_PUBLIC_SAFE_API_URL=https://safe-transaction-mainnet.safe.global/api +# NEXT_PUBLIC_SBOLD=0x50Bd66D59911F5e086Ec87aE43C811e0D059DD11 +# NEXT_PUBLIC_TROVE_EXPLORER_0=DeFi Explore|https://liquityv2.defiexplore.com/trove/{branch}/{troveId} +# NEXT_PUBLIC_TROVE_EXPLORER_1=Rails|https://rails.finance/explorer/trove/{troveId}/{branch} + +# # Uncomment one of these: +# # +# # Create an account on https://beta.graphseer.com/ and insert your API key: +# # NEXT_PUBLIC_SUBGRAPH_URL=https://graph-gateway.graphops.xyz/api/ad592eaf307cf800835a228774674bd0/subgraphs/id/6bg574MHrEZXopJDYTu7S7TAvJKEMsV111gpKLM7ZCA7 +# # +# # Or use a subgraph API key: +# NEXT_PUBLIC_SUBGRAPH_URL=https://gateway.thegraph.com/api/e6637aa857aed5275df47cc1bea63550/subgraphs/id/6bg574MHrEZXopJDYTu7S7TAvJKEMsV111gpKLM7ZCA7 + +# NEXT_PUBLIC_COLL_0_TOKEN_ID=ETH +# NEXT_PUBLIC_COLL_1_TOKEN_ID=WSTETH +# NEXT_PUBLIC_COLL_2_TOKEN_ID=RETH + +# # Use the following format for the IC strategies: +# # NEXT_PUBLIC_COLL_{index}_IC_STRATEGIES={strategy_name}:{address},{strategy_name}:{address},… +# # NEXT_PUBLIC_COLL_0_IC_STRATEGIES= +# # NEXT_PUBLIC_COLL_1_IC_STRATEGIES= +# # NEXT_PUBLIC_COLL_2_IC_STRATEGIES= + +# NEXT_PUBLIC_COLL_0_CONTRACT_ACTIVE_POOL=0xeb5a8c825582965f1d84606e078620a84ab16afe +# NEXT_PUBLIC_COLL_0_CONTRACT_ADDRESSES_REGISTRY=0x20f7c9ad66983f6523a0881d0f82406541417526 +# NEXT_PUBLIC_COLL_0_CONTRACT_BORROWER_OPERATIONS=0x372abd1810eaf23cb9d941bbe7596dfb2c46bc65 +# NEXT_PUBLIC_COLL_0_CONTRACT_COLL_SURPLUS_POOL=0xedbe2509e502c0320d2e7f8b6746a49b4b50e2bf +# NEXT_PUBLIC_COLL_0_CONTRACT_COLL_TOKEN=0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2 +# NEXT_PUBLIC_COLL_0_CONTRACT_DEFAULT_POOL=0xd4558240d50c2e219a21c9d25afd513bb6e5b1a0 +# NEXT_PUBLIC_COLL_0_CONTRACT_LEVERAGE_ZAPPER=0xdccbd7a365aee086aa3b4ede8afe895b20770ae3 +# NEXT_PUBLIC_COLL_0_CONTRACT_PRICE_FEED=0xcc5f8102eb670c89a4a3c567c13851260303c24f +# NEXT_PUBLIC_COLL_0_CONTRACT_SORTED_TROVES=0xa25269e41bd072513849f2e64ad221e84f3063f4 +# NEXT_PUBLIC_COLL_0_CONTRACT_STABILITY_POOL=0x5721cbbd64fc7ae3ef44a0a3f9a790a9264cf9bf +# NEXT_PUBLIC_COLL_0_CONTRACT_TROVE_MANAGER=0x7bcb64b2c9206a5b699ed43363f6f98d4776cf5a +# NEXT_PUBLIC_COLL_0_CONTRACT_TROVE_NFT=0x1a0fc0b843afd9140267d25d4e575cb37a838013 +# NEXT_PUBLIC_COLL_1_CONTRACT_ACTIVE_POOL=0x531a8f99c70d6a56a7cee02d6b4281650d7919a0 +# NEXT_PUBLIC_COLL_1_CONTRACT_ADDRESSES_REGISTRY=0x8d733f7ea7c23cbea7c613b6ebd845d46d3aac54 +# NEXT_PUBLIC_COLL_1_CONTRACT_BORROWER_OPERATIONS=0xa741a32f9dcfe6adba088fd0f97e90742d7d5da3 +# NEXT_PUBLIC_COLL_1_CONTRACT_COLL_SURPLUS_POOL=0x36e6cbdf68f64cf00fc3a6c634a25be32dd0a235 +# NEXT_PUBLIC_COLL_1_CONTRACT_COLL_TOKEN=0x7f39c581f595b53c5cb19bd0b3f8da6c935e2ca0 +# NEXT_PUBLIC_COLL_1_CONTRACT_DEFAULT_POOL=0xd796e1648526400386cc4d12fa05e5f11e6a22a1 +# NEXT_PUBLIC_COLL_1_CONTRACT_LEVERAGE_ZAPPER=0xe85230de04147c4ea363b21cdb801c1c19df0a56 +# NEXT_PUBLIC_COLL_1_CONTRACT_PRICE_FEED=0xe7aa2ba9e086a379d3beb224098bc634a46e314e +# NEXT_PUBLIC_COLL_1_CONTRACT_SORTED_TROVES=0x84eb85a8c25049255614f0536bea8f31682e86f1 +# NEXT_PUBLIC_COLL_1_CONTRACT_STABILITY_POOL=0x9502b7c397e9aa22fe9db7ef7daf21cd2aebe56b +# NEXT_PUBLIC_COLL_1_CONTRACT_TROVE_MANAGER=0xa2895d6a3bf110561dfe4b71ca539d84e1928b22 +# NEXT_PUBLIC_COLL_1_CONTRACT_TROVE_NFT=0x857aecebf75f1012dc18e15020c97096aea31b04 +# NEXT_PUBLIC_COLL_2_CONTRACT_ACTIVE_POOL=0x9074d72cc82dad1e13e454755aa8f144c479532f +# NEXT_PUBLIC_COLL_2_CONTRACT_ADDRESSES_REGISTRY=0x6106046f031a22713697e04c08b330ddaf3e8789 +# NEXT_PUBLIC_COLL_2_CONTRACT_BORROWER_OPERATIONS=0xe8119fc02953b27a1b48d2573855738485a17329 +# NEXT_PUBLIC_COLL_2_CONTRACT_COLL_SURPLUS_POOL=0xba4a2bd8b76df84cac98eba3f4b967d8423192bf +# NEXT_PUBLIC_COLL_2_CONTRACT_COLL_TOKEN=0xae78736cd615f374d3085123a210448e74fc6393 +# NEXT_PUBLIC_COLL_2_CONTRACT_DEFAULT_POOL=0x5cc5cefd034fdc4728d487a72ca58a410cddcd6b +# NEXT_PUBLIC_COLL_2_CONTRACT_LEVERAGE_ZAPPER=0x75036b1d6de5665c60f5c33bb4a64e8e123211a2 +# NEXT_PUBLIC_COLL_2_CONTRACT_PRICE_FEED=0x34f1e9c7dcc279ec70d3c4488eb2d80fba8b7b2b +# NEXT_PUBLIC_COLL_2_CONTRACT_SORTED_TROVES=0x14d8d8011df2b396ed2bbc4959bb73250324f386 +# NEXT_PUBLIC_COLL_2_CONTRACT_STABILITY_POOL=0xd442e41019b7f5c4dd78f50dc03726c446148695 +# NEXT_PUBLIC_COLL_2_CONTRACT_TROVE_MANAGER=0xb2b2abeb5c357a234363ff5d180912d319e3e19e +# NEXT_PUBLIC_COLL_2_CONTRACT_TROVE_NFT=0x7ae430e25b67f19b431e1d1dc048a5bcf24c0873 +# NEXT_PUBLIC_CONTRACT_BOLD_TOKEN=0x6440f144b7e50d6a8439336510312d2f54beb01d +# NEXT_PUBLIC_CONTRACT_COLLATERAL_REGISTRY=0xf949982b91c8c61e952b3ba942cbbfaef5386684 +# NEXT_PUBLIC_CONTRACT_DEBT_IN_FRONT_HELPER=0x4bb5e28fdb12891369b560f2fab3c032600677c6 +# NEXT_PUBLIC_CONTRACT_EXCHANGE_HELPERS=0x2f60bab0072abec7058017f48d7256ec288c8686 +# NEXT_PUBLIC_CONTRACT_GOVERNANCE=0x807def5e7d057df05c796f4bc75c3fe82bd6eee1 +# NEXT_PUBLIC_CONTRACT_HINT_HELPERS=0xf0cae19c96e572234398d6665cc1147a16cbe657 +# NEXT_PUBLIC_CONTRACT_LQTY_STAKING=0x4f9fbb3f1e99b56e0fe2892e623ed36a76fc605d +# NEXT_PUBLIC_CONTRACT_LQTY_TOKEN=0x6dea81c8171d0ba574754ef6f8b412f2ed88c54d +# NEXT_PUBLIC_CONTRACT_LUSD_TOKEN=0x5f98805a4e8be255a32880fdec7f6728c6568ba0 +# NEXT_PUBLIC_CONTRACT_MULTI_TROVE_GETTER=0xfa61db085510c64b83056db3a7acf3b6f631d235 +# NEXT_PUBLIC_CONTRACT_WETH=0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2 ########### # Sepolia # @@ -182,6 +182,48 @@ NEXT_PUBLIC_CONTRACT_WETH=0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2 # NEXT_PUBLIC_CONTRACT_MULTI_TROVE_GETTER=0x6fe8fa23416bd35bebe6d9a157ecd526514a2f09 # NEXT_PUBLIC_CONTRACT_WETH=0x8116d0a0e8d4f0197b428c520953f302adca0b50 +################ +# NeuraTestnet # +################ + +NEXT_PUBLIC_CHAIN_BLOCK_EXPLORER=https://testnet-blockscout.infra.neuraprotocol.io/ +NEXT_PUBLIC_CHAIN_CURRENCY=Ankr|ANKR|18 +NEXT_PUBLIC_CHAIN_ID=267 +NEXT_PUBLIC_CHAIN_NAME=NeuraTestnet +NEXT_PUBLIC_CHAIN_RPC_URL=https://testnet.rpc.neuraprotocol.io/ +NEXT_PUBLIC_SUBGRAPH_URL=https://api.goldsky.com/api/public/project_cmevjjq0rde9e01ubb66qg6es/subgraphs/liquity-fork/0.0.1/gn + +NEXT_PUBLIC_COLL_0_TOKEN_ID=WANKR +NEXT_PUBLIC_COLL_1_TOKEN_ID=USN + +NEXT_PUBLIC_COLL_0_CONTRACT_ACTIVE_POOL=0xe9786d98c6203ca0746061abfbfdeeb02e0fe5da +NEXT_PUBLIC_COLL_0_CONTRACT_ADDRESSES_REGISTRY=0x9cdc1c9582136916362d84a1dc03f5aa25e318d1 +NEXT_PUBLIC_COLL_0_CONTRACT_BORROWER_OPERATIONS=0x1ca56ac150e747074114a33223262f979ffd026c +NEXT_PUBLIC_COLL_0_CONTRACT_COLL_SURPLUS_POOL=0xed8614f48a494a8fca53978f1183516a093006a8 +NEXT_PUBLIC_COLL_0_CONTRACT_COLL_TOKEN=0xBd833b6eCC30CAEaBf81dB18BB0f1e00C6997E7a +NEXT_PUBLIC_COLL_0_CONTRACT_DEFAULT_POOL=0x2c6853ee6d9311f1c9aebad7f003999ac2f011c2 +NEXT_PUBLIC_COLL_0_CONTRACT_PRICE_FEED=0x6f2c76f8105f723df8847a4ed97d3fc2fd335b7a +NEXT_PUBLIC_COLL_0_CONTRACT_SORTED_TROVES=0xc383b06357a330d1f326d8f3e0a92c8e5d918343 +NEXT_PUBLIC_COLL_0_CONTRACT_STABILITY_POOL=0x0c8a5ebc5b8bac0dfdad159ca61fd0906bf6f53e +NEXT_PUBLIC_COLL_0_CONTRACT_TROVE_MANAGER=0x4d2044a26fde2876db02e19e4eac2e75ecb8d510 +NEXT_PUBLIC_COLL_0_CONTRACT_TROVE_NFT=0xf92ea65bd8b2c038693e385a5b2965483b1ad60f +NEXT_PUBLIC_COLL_1_CONTRACT_ACTIVE_POOL=0x9e00f9c4b769e11f1768da12a255e2b6e3ca9969 +NEXT_PUBLIC_COLL_1_CONTRACT_ADDRESSES_REGISTRY=0x9869a3ce15587b32dec8049aabd0572fffc9a5fc +NEXT_PUBLIC_COLL_1_CONTRACT_BORROWER_OPERATIONS=0x53ca33f16a98c877f19bf64a3ecc3411d049fe9f +NEXT_PUBLIC_COLL_1_CONTRACT_COLL_SURPLUS_POOL=0xbc94877d8ecd73f329ecf38fc3c032d8b82c5fbd +NEXT_PUBLIC_COLL_1_CONTRACT_COLL_TOKEN=0xe95455FEc4Be722122401B5dCAbb2428171AfF0c +NEXT_PUBLIC_COLL_1_CONTRACT_DEFAULT_POOL=0xd7662a952fb043a444ffe52115cfcf133ed238d5 +NEXT_PUBLIC_COLL_1_CONTRACT_PRICE_FEED=0x4abf5e742d9b44d4b0f0309cd3928b2e78ebd187 +NEXT_PUBLIC_COLL_1_CONTRACT_SORTED_TROVES=0xf6371a5c497170dbae162c830564fac462f206d6 +NEXT_PUBLIC_COLL_1_CONTRACT_STABILITY_POOL=0x54ccb90ef683a7256fbd600db3d64d6d1015586c +NEXT_PUBLIC_COLL_1_CONTRACT_TROVE_MANAGER=0xb048a13fad98f35470ce962ddfce8c8450822d33 +NEXT_PUBLIC_COLL_1_CONTRACT_TROVE_NFT=0x23197d6c5199fdcddd441fc4924b5356313dc936 +NEXT_PUBLIC_CONTRACT_BOLD_TOKEN=0xc13441f42e0aca71ea246aba87bdcdf646a456dd +NEXT_PUBLIC_CONTRACT_COLLATERAL_REGISTRY=0x39e982e327bb27549c447cb91ae220ad8a566afa +NEXT_PUBLIC_CONTRACT_HINT_HELPERS=0x7375ff5c5e993d2dfbff6b1d099d16971fae16b8 +NEXT_PUBLIC_CONTRACT_MULTI_TROVE_GETTER=0x580d8e94b61a2c3132b9b1f50d944ff4add3c3bb +NEXT_PUBLIC_CONTRACT_WETH=0xBd833b6eCC30CAEaBf81dB18BB0f1e00C6997E7a + ########################### # Hardhat / Anvil (local) # ########################### diff --git a/frontend/app/src/comps/StakePositionSummary/StakePositionSummary.tsx b/frontend/app/src/comps/StakePositionSummary/StakePositionSummary.tsx index 55063bb26..fcaa10155 100644 --- a/frontend/app/src/comps/StakePositionSummary/StakePositionSummary.tsx +++ b/frontend/app/src/comps/StakePositionSummary/StakePositionSummary.tsx @@ -8,7 +8,7 @@ import { TagPreview } from "@/src/comps/TagPreview/TagPreview"; import content from "@/src/content"; import { dnum18 } from "@/src/dnum-utils"; import { fmtnum } from "@/src/formatting"; -import { useGovernanceStats, useGovernanceUser, useVotingPower } from "@/src/liquity-governance"; +import { useVotingPower } from "@/src/liquity-governance"; import { useAccount } from "@/src/wagmi-utils"; import { css } from "@/styled-system/css"; import { HFlex, IconStake, InfoTooltip, TokenIcon } from "@liquity2/uikit"; @@ -29,12 +29,9 @@ export function StakePositionSummary({ }) { const account = useAccount(); - const govStats = useGovernanceStats(); - const govUser = useGovernanceUser(stakePosition?.owner ?? null); - - const stakedLqty = dnum18(govUser.data?.stakedLQTY); - const allocatedLqty = dnum18(govUser.data?.allocatedLQTY); - const totalStakedLqty = dnum18(govStats.data?.totalLQTYStaked); + const stakedLqty = dnum18(0n); + const allocatedLqty = dnum18(0n); + const totalStakedLqty = dnum18(0n); const stakedShare = stakedLqty && totalStakedLqty && dn.gt(totalStakedLqty, 0) ? dn.div(stakedLqty, totalStakedLqty) @@ -42,7 +39,7 @@ export function StakePositionSummary({ const appear = useAppear( !account.isConnected || ( - loadingState === "success" && govUser.status === "success" + loadingState === "success" ), ); @@ -424,7 +421,7 @@ export function StakePositionSummary({

{content.stakeScreen.infoTooltips.votingPower}

- {account.address && (govUser.data?.stakedLQTY ?? 0n) > 0n && ( + {account.address && (0n) > 0n && (
; - vetoLQTY: Scalars['BigInt']['output']; - vetoOffset: Scalars['BigInt']['output']; - voteLQTY: Scalars['BigInt']['output']; - voteOffset: Scalars['BigInt']['output']; -}; - -export type GovernanceAllocationIndex = { - __typename?: 'GovernanceAllocationIndex'; - id: Scalars['ID']['output']; - initiative: GovernanceInitiative; - latestAllocation: GovernanceAllocation; - user?: Maybe; -}; - -export type GovernanceAllocationIndex_Filter = { - /** Filter for the block changed event. */ - _change_block?: InputMaybe; - and?: InputMaybe>>; - id?: InputMaybe; - id_gt?: InputMaybe; - id_gte?: InputMaybe; - id_in?: InputMaybe>; - id_lt?: InputMaybe; - id_lte?: InputMaybe; - id_not?: InputMaybe; - id_not_in?: InputMaybe>; - initiative?: InputMaybe; - initiative_?: InputMaybe; - initiative_contains?: InputMaybe; - initiative_contains_nocase?: InputMaybe; - initiative_ends_with?: InputMaybe; - initiative_ends_with_nocase?: InputMaybe; - initiative_gt?: InputMaybe; - initiative_gte?: InputMaybe; - initiative_in?: InputMaybe>; - initiative_lt?: InputMaybe; - initiative_lte?: InputMaybe; - initiative_not?: InputMaybe; - initiative_not_contains?: InputMaybe; - initiative_not_contains_nocase?: InputMaybe; - initiative_not_ends_with?: InputMaybe; - initiative_not_ends_with_nocase?: InputMaybe; - initiative_not_in?: InputMaybe>; - initiative_not_starts_with?: InputMaybe; - initiative_not_starts_with_nocase?: InputMaybe; - initiative_starts_with?: InputMaybe; - initiative_starts_with_nocase?: InputMaybe; - latestAllocation?: InputMaybe; - latestAllocation_?: InputMaybe; - latestAllocation_contains?: InputMaybe; - latestAllocation_contains_nocase?: InputMaybe; - latestAllocation_ends_with?: InputMaybe; - latestAllocation_ends_with_nocase?: InputMaybe; - latestAllocation_gt?: InputMaybe; - latestAllocation_gte?: InputMaybe; - latestAllocation_in?: InputMaybe>; - latestAllocation_lt?: InputMaybe; - latestAllocation_lte?: InputMaybe; - latestAllocation_not?: InputMaybe; - latestAllocation_not_contains?: InputMaybe; - latestAllocation_not_contains_nocase?: InputMaybe; - latestAllocation_not_ends_with?: InputMaybe; - latestAllocation_not_ends_with_nocase?: InputMaybe; - latestAllocation_not_in?: InputMaybe>; - latestAllocation_not_starts_with?: InputMaybe; - latestAllocation_not_starts_with_nocase?: InputMaybe; - latestAllocation_starts_with?: InputMaybe; - latestAllocation_starts_with_nocase?: InputMaybe; - or?: InputMaybe>>; - user?: InputMaybe; - user_contains?: InputMaybe; - user_contains_nocase?: InputMaybe; - user_ends_with?: InputMaybe; - user_ends_with_nocase?: InputMaybe; - user_gt?: InputMaybe; - user_gte?: InputMaybe; - user_in?: InputMaybe>; - user_lt?: InputMaybe; - user_lte?: InputMaybe; - user_not?: InputMaybe; - user_not_contains?: InputMaybe; - user_not_contains_nocase?: InputMaybe; - user_not_ends_with?: InputMaybe; - user_not_ends_with_nocase?: InputMaybe; - user_not_in?: InputMaybe>; - user_not_starts_with?: InputMaybe; - user_not_starts_with_nocase?: InputMaybe; - user_starts_with?: InputMaybe; - user_starts_with_nocase?: InputMaybe; -}; - -export enum GovernanceAllocationIndex_OrderBy { - Id = 'id', - Initiative = 'initiative', - InitiativeId = 'initiative__id', - InitiativeRegistered = 'initiative__registered', - LatestAllocation = 'latestAllocation', - LatestAllocationEpoch = 'latestAllocation__epoch', - LatestAllocationId = 'latestAllocation__id', - LatestAllocationUser = 'latestAllocation__user', - LatestAllocationVetoLqty = 'latestAllocation__vetoLQTY', - LatestAllocationVetoOffset = 'latestAllocation__vetoOffset', - LatestAllocationVoteLqty = 'latestAllocation__voteLQTY', - LatestAllocationVoteOffset = 'latestAllocation__voteOffset', - User = 'user' -} - -export type GovernanceAllocation_Filter = { - /** Filter for the block changed event. */ - _change_block?: InputMaybe; - and?: InputMaybe>>; - epoch?: InputMaybe; - epoch_gt?: InputMaybe; - epoch_gte?: InputMaybe; - epoch_in?: InputMaybe>; - epoch_lt?: InputMaybe; - epoch_lte?: InputMaybe; - epoch_not?: InputMaybe; - epoch_not_in?: InputMaybe>; - id?: InputMaybe; - id_gt?: InputMaybe; - id_gte?: InputMaybe; - id_in?: InputMaybe>; - id_lt?: InputMaybe; - id_lte?: InputMaybe; - id_not?: InputMaybe; - id_not_in?: InputMaybe>; - initiative?: InputMaybe; - initiative_?: InputMaybe; - initiative_contains?: InputMaybe; - initiative_contains_nocase?: InputMaybe; - initiative_ends_with?: InputMaybe; - initiative_ends_with_nocase?: InputMaybe; - initiative_gt?: InputMaybe; - initiative_gte?: InputMaybe; - initiative_in?: InputMaybe>; - initiative_lt?: InputMaybe; - initiative_lte?: InputMaybe; - initiative_not?: InputMaybe; - initiative_not_contains?: InputMaybe; - initiative_not_contains_nocase?: InputMaybe; - initiative_not_ends_with?: InputMaybe; - initiative_not_ends_with_nocase?: InputMaybe; - initiative_not_in?: InputMaybe>; - initiative_not_starts_with?: InputMaybe; - initiative_not_starts_with_nocase?: InputMaybe; - initiative_starts_with?: InputMaybe; - initiative_starts_with_nocase?: InputMaybe; - or?: InputMaybe>>; - user?: InputMaybe; - user_contains?: InputMaybe; - user_contains_nocase?: InputMaybe; - user_ends_with?: InputMaybe; - user_ends_with_nocase?: InputMaybe; - user_gt?: InputMaybe; - user_gte?: InputMaybe; - user_in?: InputMaybe>; - user_lt?: InputMaybe; - user_lte?: InputMaybe; - user_not?: InputMaybe; - user_not_contains?: InputMaybe; - user_not_contains_nocase?: InputMaybe; - user_not_ends_with?: InputMaybe; - user_not_ends_with_nocase?: InputMaybe; - user_not_in?: InputMaybe>; - user_not_starts_with?: InputMaybe; - user_not_starts_with_nocase?: InputMaybe; - user_starts_with?: InputMaybe; - user_starts_with_nocase?: InputMaybe; - vetoLQTY?: InputMaybe; - vetoLQTY_gt?: InputMaybe; - vetoLQTY_gte?: InputMaybe; - vetoLQTY_in?: InputMaybe>; - vetoLQTY_lt?: InputMaybe; - vetoLQTY_lte?: InputMaybe; - vetoLQTY_not?: InputMaybe; - vetoLQTY_not_in?: InputMaybe>; - vetoOffset?: InputMaybe; - vetoOffset_gt?: InputMaybe; - vetoOffset_gte?: InputMaybe; - vetoOffset_in?: InputMaybe>; - vetoOffset_lt?: InputMaybe; - vetoOffset_lte?: InputMaybe; - vetoOffset_not?: InputMaybe; - vetoOffset_not_in?: InputMaybe>; - voteLQTY?: InputMaybe; - voteLQTY_gt?: InputMaybe; - voteLQTY_gte?: InputMaybe; - voteLQTY_in?: InputMaybe>; - voteLQTY_lt?: InputMaybe; - voteLQTY_lte?: InputMaybe; - voteLQTY_not?: InputMaybe; - voteLQTY_not_in?: InputMaybe>; - voteOffset?: InputMaybe; - voteOffset_gt?: InputMaybe; - voteOffset_gte?: InputMaybe; - voteOffset_in?: InputMaybe>; - voteOffset_lt?: InputMaybe; - voteOffset_lte?: InputMaybe; - voteOffset_not?: InputMaybe; - voteOffset_not_in?: InputMaybe>; -}; - -export enum GovernanceAllocation_OrderBy { - Epoch = 'epoch', - Id = 'id', - Initiative = 'initiative', - InitiativeId = 'initiative__id', - InitiativeRegistered = 'initiative__registered', - User = 'user', - VetoLqty = 'vetoLQTY', - VetoOffset = 'vetoOffset', - VoteLqty = 'voteLQTY', - VoteOffset = 'voteOffset' -} - -export type GovernanceInitiative = { - __typename?: 'GovernanceInitiative'; - id: Scalars['ID']['output']; - registered: Scalars['Boolean']['output']; -}; - -export type GovernanceInitiative_Filter = { - /** Filter for the block changed event. */ - _change_block?: InputMaybe; - and?: InputMaybe>>; - id?: InputMaybe; - id_gt?: InputMaybe; - id_gte?: InputMaybe; - id_in?: InputMaybe>; - id_lt?: InputMaybe; - id_lte?: InputMaybe; - id_not?: InputMaybe; - id_not_in?: InputMaybe>; - or?: InputMaybe>>; - registered?: InputMaybe; - registered_in?: InputMaybe>; - registered_not?: InputMaybe; - registered_not_in?: InputMaybe>; -}; - -export enum GovernanceInitiative_OrderBy { - Id = 'id', - Registered = 'registered' -} - -export type GovernanceVotingPower = { - __typename?: 'GovernanceVotingPower'; - allocatedLQTY: Scalars['BigInt']['output']; - allocatedOffset: Scalars['BigInt']['output']; - id: Scalars['ID']['output']; - unallocatedLQTY: Scalars['BigInt']['output']; - unallocatedOffset: Scalars['BigInt']['output']; -}; - -export type GovernanceVotingPower_Filter = { - /** Filter for the block changed event. */ - _change_block?: InputMaybe; - allocatedLQTY?: InputMaybe; - allocatedLQTY_gt?: InputMaybe; - allocatedLQTY_gte?: InputMaybe; - allocatedLQTY_in?: InputMaybe>; - allocatedLQTY_lt?: InputMaybe; - allocatedLQTY_lte?: InputMaybe; - allocatedLQTY_not?: InputMaybe; - allocatedLQTY_not_in?: InputMaybe>; - allocatedOffset?: InputMaybe; - allocatedOffset_gt?: InputMaybe; - allocatedOffset_gte?: InputMaybe; - allocatedOffset_in?: InputMaybe>; - allocatedOffset_lt?: InputMaybe; - allocatedOffset_lte?: InputMaybe; - allocatedOffset_not?: InputMaybe; - allocatedOffset_not_in?: InputMaybe>; - and?: InputMaybe>>; - id?: InputMaybe; - id_gt?: InputMaybe; - id_gte?: InputMaybe; - id_in?: InputMaybe>; - id_lt?: InputMaybe; - id_lte?: InputMaybe; - id_not?: InputMaybe; - id_not_in?: InputMaybe>; - or?: InputMaybe>>; - unallocatedLQTY?: InputMaybe; - unallocatedLQTY_gt?: InputMaybe; - unallocatedLQTY_gte?: InputMaybe; - unallocatedLQTY_in?: InputMaybe>; - unallocatedLQTY_lt?: InputMaybe; - unallocatedLQTY_lte?: InputMaybe; - unallocatedLQTY_not?: InputMaybe; - unallocatedLQTY_not_in?: InputMaybe>; - unallocatedOffset?: InputMaybe; - unallocatedOffset_gt?: InputMaybe; - unallocatedOffset_gte?: InputMaybe; - unallocatedOffset_in?: InputMaybe>; - unallocatedOffset_lt?: InputMaybe; - unallocatedOffset_lte?: InputMaybe; - unallocatedOffset_not?: InputMaybe; - unallocatedOffset_not_in?: InputMaybe>; -}; - -export enum GovernanceVotingPower_OrderBy { - AllocatedLqty = 'allocatedLQTY', - AllocatedOffset = 'allocatedOffset', - Id = 'id', - UnallocatedLqty = 'unallocatedLQTY', - UnallocatedOffset = 'unallocatedOffset' -} - export type InterestBatch = { __typename?: 'InterestBatch'; annualInterestRate: Scalars['BigInt']['output']; @@ -608,6 +292,7 @@ export type InterestBatch = { debt: Scalars['BigInt']['output']; id: Scalars['ID']['output']; troves: Array; + updatedAt: Scalars['BigInt']['output']; }; @@ -696,6 +381,14 @@ export type InterestBatch_Filter = { id_not_in?: InputMaybe>; or?: InputMaybe>>; troves_?: InputMaybe; + updatedAt?: InputMaybe; + updatedAt_gt?: InputMaybe; + updatedAt_gte?: InputMaybe; + updatedAt_in?: InputMaybe>; + updatedAt_lt?: InputMaybe; + updatedAt_lte?: InputMaybe; + updatedAt_not?: InputMaybe; + updatedAt_not_in?: InputMaybe>; }; export enum InterestBatch_OrderBy { @@ -709,15 +402,19 @@ export enum InterestBatch_OrderBy { CollateralMinCollRatio = 'collateral__minCollRatio', Debt = 'debt', Id = 'id', - Troves = 'troves' + Troves = 'troves', + UpdatedAt = 'updatedAt' } export type InterestRateBracket = { __typename?: 'InterestRateBracket'; collateral: Collateral; id: Scalars['ID']['output']; + pendingDebtTimesOneYearD36: Scalars['BigInt']['output']; rate: Scalars['BigInt']['output']; + sumDebtTimesRateD36: Scalars['BigInt']['output']; totalDebt: Scalars['BigInt']['output']; + updatedAt: Scalars['BigInt']['output']; }; export type InterestRateBracket_Filter = { @@ -754,6 +451,14 @@ export type InterestRateBracket_Filter = { id_not?: InputMaybe; id_not_in?: InputMaybe>; or?: InputMaybe>>; + pendingDebtTimesOneYearD36?: InputMaybe; + pendingDebtTimesOneYearD36_gt?: InputMaybe; + pendingDebtTimesOneYearD36_gte?: InputMaybe; + pendingDebtTimesOneYearD36_in?: InputMaybe>; + pendingDebtTimesOneYearD36_lt?: InputMaybe; + pendingDebtTimesOneYearD36_lte?: InputMaybe; + pendingDebtTimesOneYearD36_not?: InputMaybe; + pendingDebtTimesOneYearD36_not_in?: InputMaybe>; rate?: InputMaybe; rate_gt?: InputMaybe; rate_gte?: InputMaybe; @@ -762,6 +467,14 @@ export type InterestRateBracket_Filter = { rate_lte?: InputMaybe; rate_not?: InputMaybe; rate_not_in?: InputMaybe>; + sumDebtTimesRateD36?: InputMaybe; + sumDebtTimesRateD36_gt?: InputMaybe; + sumDebtTimesRateD36_gte?: InputMaybe; + sumDebtTimesRateD36_in?: InputMaybe>; + sumDebtTimesRateD36_lt?: InputMaybe; + sumDebtTimesRateD36_lte?: InputMaybe; + sumDebtTimesRateD36_not?: InputMaybe; + sumDebtTimesRateD36_not_in?: InputMaybe>; totalDebt?: InputMaybe; totalDebt_gt?: InputMaybe; totalDebt_gte?: InputMaybe; @@ -770,6 +483,14 @@ export type InterestRateBracket_Filter = { totalDebt_lte?: InputMaybe; totalDebt_not?: InputMaybe; totalDebt_not_in?: InputMaybe>; + updatedAt?: InputMaybe; + updatedAt_gt?: InputMaybe; + updatedAt_gte?: InputMaybe; + updatedAt_in?: InputMaybe>; + updatedAt_lt?: InputMaybe; + updatedAt_lte?: InputMaybe; + updatedAt_not?: InputMaybe; + updatedAt_not_in?: InputMaybe>; }; export enum InterestRateBracket_OrderBy { @@ -778,8 +499,11 @@ export enum InterestRateBracket_OrderBy { CollateralId = 'collateral__id', CollateralMinCollRatio = 'collateral__minCollRatio', Id = 'id', + PendingDebtTimesOneYearD36 = 'pendingDebtTimesOneYearD36', Rate = 'rate', - TotalDebt = 'totalDebt' + SumDebtTimesRateD36 = 'sumDebtTimesRateD36', + TotalDebt = 'totalDebt', + UpdatedAt = 'updatedAt' } /** Defines the order direction, either ascending or descending */ @@ -798,14 +522,6 @@ export type Query = { collateralAddresses?: Maybe; collateralAddresses_collection: Array; collaterals: Array; - governanceAllocation?: Maybe; - governanceAllocationIndex?: Maybe; - governanceAllocationIndexes: Array; - governanceAllocations: Array; - governanceInitiative?: Maybe; - governanceInitiatives: Array; - governanceVotingPower?: Maybe; - governanceVotingPowers: Array; interestBatch?: Maybe; interestBatches: Array; interestRateBracket?: Maybe; @@ -874,78 +590,6 @@ export type QueryCollateralsArgs = { }; -export type QueryGovernanceAllocationArgs = { - block?: InputMaybe; - id: Scalars['ID']['input']; - subgraphError?: _SubgraphErrorPolicy_; -}; - - -export type QueryGovernanceAllocationIndexArgs = { - block?: InputMaybe; - id: Scalars['ID']['input']; - subgraphError?: _SubgraphErrorPolicy_; -}; - - -export type QueryGovernanceAllocationIndexesArgs = { - block?: InputMaybe; - first?: InputMaybe; - orderBy?: InputMaybe; - orderDirection?: InputMaybe; - skip?: InputMaybe; - subgraphError?: _SubgraphErrorPolicy_; - where?: InputMaybe; -}; - - -export type QueryGovernanceAllocationsArgs = { - block?: InputMaybe; - first?: InputMaybe; - orderBy?: InputMaybe; - orderDirection?: InputMaybe; - skip?: InputMaybe; - subgraphError?: _SubgraphErrorPolicy_; - where?: InputMaybe; -}; - - -export type QueryGovernanceInitiativeArgs = { - block?: InputMaybe; - id: Scalars['ID']['input']; - subgraphError?: _SubgraphErrorPolicy_; -}; - - -export type QueryGovernanceInitiativesArgs = { - block?: InputMaybe; - first?: InputMaybe; - orderBy?: InputMaybe; - orderDirection?: InputMaybe; - skip?: InputMaybe; - subgraphError?: _SubgraphErrorPolicy_; - where?: InputMaybe; -}; - - -export type QueryGovernanceVotingPowerArgs = { - block?: InputMaybe; - id: Scalars['ID']['input']; - subgraphError?: _SubgraphErrorPolicy_; -}; - - -export type QueryGovernanceVotingPowersArgs = { - block?: InputMaybe; - first?: InputMaybe; - orderBy?: InputMaybe; - orderDirection?: InputMaybe; - skip?: InputMaybe; - subgraphError?: _SubgraphErrorPolicy_; - where?: InputMaybe; -}; - - export type QueryInterestBatchArgs = { block?: InputMaybe; id: Scalars['ID']['input']; @@ -1009,14 +653,6 @@ export type Subscription = { collateralAddresses?: Maybe; collateralAddresses_collection: Array; collaterals: Array; - governanceAllocation?: Maybe; - governanceAllocationIndex?: Maybe; - governanceAllocationIndexes: Array; - governanceAllocations: Array; - governanceInitiative?: Maybe; - governanceInitiatives: Array; - governanceVotingPower?: Maybe; - governanceVotingPowers: Array; interestBatch?: Maybe; interestBatches: Array; interestRateBracket?: Maybe; @@ -1085,78 +721,6 @@ export type SubscriptionCollateralsArgs = { }; -export type SubscriptionGovernanceAllocationArgs = { - block?: InputMaybe; - id: Scalars['ID']['input']; - subgraphError?: _SubgraphErrorPolicy_; -}; - - -export type SubscriptionGovernanceAllocationIndexArgs = { - block?: InputMaybe; - id: Scalars['ID']['input']; - subgraphError?: _SubgraphErrorPolicy_; -}; - - -export type SubscriptionGovernanceAllocationIndexesArgs = { - block?: InputMaybe; - first?: InputMaybe; - orderBy?: InputMaybe; - orderDirection?: InputMaybe; - skip?: InputMaybe; - subgraphError?: _SubgraphErrorPolicy_; - where?: InputMaybe; -}; - - -export type SubscriptionGovernanceAllocationsArgs = { - block?: InputMaybe; - first?: InputMaybe; - orderBy?: InputMaybe; - orderDirection?: InputMaybe; - skip?: InputMaybe; - subgraphError?: _SubgraphErrorPolicy_; - where?: InputMaybe; -}; - - -export type SubscriptionGovernanceInitiativeArgs = { - block?: InputMaybe; - id: Scalars['ID']['input']; - subgraphError?: _SubgraphErrorPolicy_; -}; - - -export type SubscriptionGovernanceInitiativesArgs = { - block?: InputMaybe; - first?: InputMaybe; - orderBy?: InputMaybe; - orderDirection?: InputMaybe; - skip?: InputMaybe; - subgraphError?: _SubgraphErrorPolicy_; - where?: InputMaybe; -}; - - -export type SubscriptionGovernanceVotingPowerArgs = { - block?: InputMaybe; - id: Scalars['ID']['input']; - subgraphError?: _SubgraphErrorPolicy_; -}; - - -export type SubscriptionGovernanceVotingPowersArgs = { - block?: InputMaybe; - first?: InputMaybe; - orderBy?: InputMaybe; - orderDirection?: InputMaybe; - skip?: InputMaybe; - subgraphError?: _SubgraphErrorPolicy_; - where?: InputMaybe; -}; - - export type SubscriptionInterestBatchArgs = { block?: InputMaybe; id: Scalars['ID']['input']; @@ -1451,6 +1015,7 @@ export enum Trove_OrderBy { InterestBatchColl = 'interestBatch__coll', InterestBatchDebt = 'interestBatch__debt', InterestBatchId = 'interestBatch__id', + InterestBatchUpdatedAt = 'interestBatch__updatedAt', InterestRate = 'interestRate', LastUserActionAt = 'lastUserActionAt', MightBeLeveraged = 'mightBeLeveraged', @@ -1538,25 +1103,6 @@ export type AllInterestRateBracketsQueryVariables = Exact<{ [key: string]: never export type AllInterestRateBracketsQuery = { __typename?: 'Query', interestRateBrackets: Array<{ __typename?: 'InterestRateBracket', rate: string, totalDebt: string, collateral: { __typename?: 'Collateral', collIndex: number } }> }; -export type GovernanceGlobalDataQueryVariables = Exact<{ [key: string]: never; }>; - - -export type GovernanceGlobalDataQuery = { __typename?: 'Query', governanceInitiatives: Array<{ __typename?: 'GovernanceInitiative', id: string }>, governanceVotingPower?: { __typename?: 'GovernanceVotingPower', allocatedLQTY: string, allocatedOffset: string, unallocatedLQTY: string, unallocatedOffset: string } | null }; - -export type UserAllocationHistoryQueryVariables = Exact<{ - user?: InputMaybe; -}>; - - -export type UserAllocationHistoryQuery = { __typename?: 'Query', governanceAllocations: Array<{ __typename?: 'GovernanceAllocation', epoch: string, voteLQTY: string, vetoLQTY: string, voteOffset: string, vetoOffset: string, initiative: { __typename?: 'GovernanceInitiative', id: string } }> }; - -export type TotalAllocationHistoryQueryVariables = Exact<{ - initiative?: InputMaybe; -}>; - - -export type TotalAllocationHistoryQuery = { __typename?: 'Query', governanceAllocations: Array<{ __typename?: 'GovernanceAllocation', epoch: string, voteLQTY: string, vetoLQTY: string, voteOffset: string, vetoOffset: string }> }; - export class TypedDocumentString extends String implements DocumentTypeDecoration @@ -1654,52 +1200,4 @@ export const AllInterestRateBracketsDocument = new TypedDocumentString(` totalDebt } } - `) as unknown as TypedDocumentString; -export const GovernanceGlobalDataDocument = new TypedDocumentString(` - query GovernanceGlobalData { - governanceInitiatives { - id - } - governanceVotingPower(id: "total") { - allocatedLQTY - allocatedOffset - unallocatedLQTY - unallocatedOffset - } -} - `) as unknown as TypedDocumentString; -export const UserAllocationHistoryDocument = new TypedDocumentString(` - query UserAllocationHistory($user: String) { - governanceAllocations( - where: {user: $user} - orderBy: epoch - orderDirection: desc - first: 1000 - ) { - epoch - initiative { - id - } - voteLQTY - vetoLQTY - voteOffset - vetoOffset - } -} - `) as unknown as TypedDocumentString; -export const TotalAllocationHistoryDocument = new TypedDocumentString(` - query TotalAllocationHistory($initiative: String) { - governanceAllocations( - where: {initiative: $initiative, user: null} - orderBy: epoch - orderDirection: desc - first: 1000 - ) { - epoch - voteLQTY - vetoLQTY - voteOffset - vetoOffset - } -} - `) as unknown as TypedDocumentString; \ No newline at end of file + `) as unknown as TypedDocumentString; \ No newline at end of file diff --git a/frontend/app/src/liquity-governance.ts b/frontend/app/src/liquity-governance.ts index 22f43f3cd..f5c252793 100644 --- a/frontend/app/src/liquity-governance.ts +++ b/frontend/app/src/liquity-governance.ts @@ -1,25 +1,13 @@ -import type { Address, Dnum, Initiative } from "@/src/types"; +import type { Address, Dnum} from "@/src/types"; import type { UseQueryResult } from "@tanstack/react-query"; import type { Config as WagmiConfig } from "wagmi"; import { BribeInitiative } from "@/src/abi/BribeInitiative"; import { getProtocolContract } from "@/src/contracts"; -import { dnum18, DNUM_0, jsonStringifyWithDnum } from "@/src/dnum-utils"; -import { CHAIN_CONTRACT_MULTICALL, KNOWN_INITIATIVES_URL, LIQUITY_GOVERNANCE_URL } from "@/src/env"; -import { - getGovernanceGlobalData, - getTotalAllocationHistoryFromSubgraph, - getUserAllocationHistoryFromSubgraph, -} from "@/src/subgraph"; -import { jsonStringifyWithBigInt } from "@/src/utils"; -import { vAddress } from "@/src/valibot-utils"; -import { useRaf } from "@liquity2/uikit"; +import { dnum18} from "@/src/dnum-utils"; import { useQuery } from "@tanstack/react-query"; -import * as dn from "dnum"; -import { useMemo } from "react"; -import * as v from "valibot"; -import { erc20Abi, parseAbi } from "viem"; -import { useConfig as useWagmiConfig, useReadContract, useReadContracts } from "wagmi"; +import { erc20Abi} from "viem"; +import { useConfig as useWagmiConfig, useReadContracts } from "wagmi"; import { readContract, readContracts } from "wagmi/actions"; export type InitiativeStatus = @@ -106,74 +94,8 @@ export function useGovernanceState() { }); } -const KnownInitiativesSchema = v.record( - v.pipe( - vAddress(), - v.transform((address) => address.toLowerCase()), - ), - v.pipe( - v.object({ - name: v.string(), - name_link: v.optional(v.pipe(v.string(), v.url())), - group: v.string(), - }), - v.transform(({ name_link = null, ...initiative }) => ({ - ...initiative, - url: name_link, - })), - ), -); - -function useKnownInitiatives() { - return useQuery({ - queryKey: ["knownInitiatives"], - queryFn: async () => { - if (!KNOWN_INITIATIVES_URL) return null; - - const response = await fetch(KNOWN_INITIATIVES_URL); - const data = await response.json(); - return v.parse(KnownInitiativesSchema, data); - }, - }); -} - -function useGovernanceGlobalData() { - return useQuery({ - queryKey: ["governanceGlobalData"], - queryFn: getGovernanceGlobalData, - }); -} - export function useNamedInitiatives() { - const knownInitiatives = useKnownInitiatives(); - const governanceGlobal = useGovernanceGlobalData(); - - return useQuery({ - queryKey: ["namedInitiatives"], - enabled: ( - knownInitiatives.isSuccess && governanceGlobal.isSuccess - || knownInitiatives.isError - || governanceGlobal.isError - ), - queryFn: () => { - if (knownInitiatives.isError) throw knownInitiatives.error; - if (governanceGlobal.isError) throw governanceGlobal.error; - if (knownInitiatives.isPending || governanceGlobal.isPending) throw new Error("should not happen"); // see enabled - - return governanceGlobal.data.registeredInitiatives.map((address): Initiative => { - const ki = knownInitiatives.data?.[address]; - return { - address, - name: ki?.name ?? null, - pairVolume: null, - protocol: ki?.group ?? null, - tvl: null, - url: ki?.url ?? null, - votesDistribution: null, - }; - }); - }, - }); + throw new Error("undefined subgraph query"); } export function useInitiativesStates(initiatives: Address[]) { @@ -259,27 +181,10 @@ export async function getUserAllocations( account: Address, initiatives?: Address[], ) { - if (!initiatives) { - initiatives = (await getGovernanceGlobalData()).registeredInitiatives; - } - - const Governance = getProtocolContract("Governance"); - - const allocationsByInitiative = await readContracts(wagmiConfig, { - allowFailure: false, - contracts: initiatives.map((address) => ({ - ...Governance, - functionName: "lqtyAllocatedByUserToInitiative", - args: [account, address], - } as const)), - }); - - return allocationsByInitiative.map((allocation, index) => { - const initiative = initiatives[index]; - if (!initiative) throw new Error(); // should never happen - const [voteLQTY, voteOffset, vetoLQTY, vetoOffset] = allocation; - return { voteLQTY, voteOffset, vetoLQTY, vetoOffset, initiative }; - }); + wagmiConfig; + account; + initiatives; + throw new Error("undefined subgraph query"); } export async function getUserAllocatedInitiatives( @@ -287,10 +192,10 @@ export async function getUserAllocatedInitiatives( account: Address, initiatives?: Address[], ) { - const allocations = await getUserAllocations(wagmiConfig, account, initiatives); - return allocations - .filter(({ voteLQTY, vetoLQTY }) => (voteLQTY + vetoLQTY) > 0n) - .map(({ initiative }) => initiative); + wagmiConfig; + account; + initiatives; + throw new Error("undefined subgraph query"); } export async function getUserStates( @@ -322,41 +227,8 @@ export async function getUserStates( } export function useGovernanceUser(account: Address | null) { - const initiatives = useNamedInitiatives(); - const wagmiConfig = useWagmiConfig(); - - let queryFn = async () => { - if (!account || !initiatives.data) return null; - - const [userState, allocations] = await Promise.all([ - getUserStates(wagmiConfig, account), - getUserAllocations( - wagmiConfig, - account, - initiatives.data.map((i) => i.address), - ), - ]); - - return { ...userState, allocations }; - }; - - return useQuery({ - queryKey: [ - "GovernanceUser", - account, - jsonStringifyWithDnum(initiatives.data), - ], - queryFn, - }); -} - -function useLatestBlockTimestampInMilliseconds() { - return useReadContract({ - address: CHAIN_CONTRACT_MULTICALL, - abi: parseAbi(["function getCurrentBlockTimestamp() view returns (uint256)"]), - functionName: "getCurrentBlockTimestamp", - query: { select: (blockTimestamp) => blockTimestamp * 1000n }, - }); + account; + throw new Error("undefined subgraph query"); } // votingPower(t) = lqty * t - offset @@ -368,72 +240,19 @@ export function votingPower( return stakedLQTY * timestampInSeconds - offset; } -function votingPowerMs( - stakedLQTY: bigint, - offset: bigint, - timestampInMilliseconds: bigint, -) { - return (stakedLQTY * timestampInMilliseconds - offset * 1000n) / 1000n; -} - export function useVotingPower( account: Address | null, callback: (share: Dnum | null) => void, updatesPerSecond: number = 30, ) { - const govStats = useGovernanceStats(); - const govUser = useGovernanceUser(account); - const blockTimestamp = useLatestBlockTimestampInMilliseconds(); - const startTime = useMemo(() => BigInt(Date.now()), []); - - useRaf(() => { - if (!govStats.data || !govUser.data || !blockTimestamp.data) { - callback(null); - return; - } - - const { totalLQTYStaked, totalOffset } = govStats.data; - const userLQTYStaked = govUser.data.allocatedLQTY + govUser.data.unallocatedLQTY; - const userOffset = govUser.data.allocatedOffset + govUser.data.unallocatedOffset; - - const timeElapsed = BigInt(Date.now()) - startTime; - const correctedStartTime = startTime > blockTimestamp.data ? startTime : blockTimestamp.data; - const timestamp = correctedStartTime + timeElapsed; - const userVp = votingPowerMs(userLQTYStaked, userOffset, timestamp); - const totalVP = votingPowerMs(totalLQTYStaked, totalOffset, timestamp); - - // pctShare(t) = userVotingPower(t) / totalVotingPower(t) - callback( - totalVP === 0n ? DNUM_0 : dn.div( - dnum18(userVp), - dnum18(totalVP), - ), - ); - }, updatesPerSecond); + account; + callback; + updatesPerSecond; + throw new Error("undefined subgraph query"); } export function useGovernanceStats() { - const governanceGlobal = useGovernanceGlobalData(); - - return useQuery({ - queryKey: ["governanceStats"], - enabled: !governanceGlobal.isPending, - queryFn: () => { - if (governanceGlobal.isError) throw governanceGlobal.error; - if (governanceGlobal.isPending) throw new Error("should not happen"); // see enabled - - return { - totalLQTYStaked: ( - governanceGlobal.data.totalVotingPower.allocatedLQTY - + governanceGlobal.data.totalVotingPower.unallocatedLQTY - ), - totalOffset: ( - governanceGlobal.data.totalVotingPower.allocatedOffset - + governanceGlobal.data.totalVotingPower.unallocatedOffset - ), - }; - }, - }); + throw new Error("undefined subgraph query"); } type ClaimData = { @@ -554,288 +373,9 @@ export function useCurrentEpochBribes( }); } -const AllocationSchema = v.object({ - epoch: v.number(), - voteLQTY: v.pipe(v.string(), v.transform((x) => BigInt(x))), - vetoLQTY: v.pipe(v.string(), v.transform((x) => BigInt(x))), - voteOffset: v.pipe(v.string(), v.transform((x) => BigInt(x))), - vetoOffset: v.pipe(v.string(), v.transform((x) => BigInt(x))), -}); - -const TotalAllocationHistorySchema = v.array(AllocationSchema); - -const UserAllocationSchema = v.object({ - ...AllocationSchema.entries, - initiative: v.string(), -}); - -const UserAllocationHistorySchema = v.array(UserAllocationSchema); - -// A user's allocation history ordered by descending epoch -async function getUserAllocationHistory(user: Address) { - if (LIQUITY_GOVERNANCE_URL) { - const response = await fetch(`${LIQUITY_GOVERNANCE_URL}/allocation/user/${user.toLowerCase()}.json`); - return v.parse(UserAllocationHistorySchema, await response.json()).sort((a, b) => b.epoch - a.epoch); - } else { - return getUserAllocationHistoryFromSubgraph(user); - } -} - -// An initiative's total allocation history ordered by descending epoch -async function getTotalAllocationHistory(initiative: Address) { - if (LIQUITY_GOVERNANCE_URL) { - const response = await fetch(`${LIQUITY_GOVERNANCE_URL}/allocation/total/${initiative.toLowerCase()}.json`); - return v.parse(TotalAllocationHistorySchema, await response.json()).sort((a, b) => b.epoch - a.epoch); - } else { - return getTotalAllocationHistoryFromSubgraph(initiative); - } -} - -async function getLatestCompletedEpoch(currentEpoch: bigint) { - if (LIQUITY_GOVERNANCE_URL) { - const response = await fetch(`${LIQUITY_GOVERNANCE_URL}/latest_completed_epoch.json`); - return v.parse(v.number(), await response.json()); - } else { - return Number(currentEpoch) - 1; - } -} - -// limit checks to the last 52 epochs -const BRIBING_CHECK_EPOCH_LIMIT = 52; - export function useBribingClaim( account: Address | null, ): UseQueryResult { - const wagmiConfig = useWagmiConfig(); - const govState = useGovernanceState(); - const govUser = useGovernanceUser(account); - const initiatives = useNamedInitiatives(); - - return useQuery({ - queryKey: [ - "bribingClaim", - account, - String(govState.data?.epoch), - jsonStringifyWithBigInt(govUser.data), - ], - queryFn: async () => { - if (!account || !govState.data || !govUser.data || !initiatives.data) { - return null; - } - - const currentEpoch = govState.data.epoch; - const epochDuration = govState.data.epochEnd - govState.data.epochStart; - const initiativesToCheck = initiatives.data.map(({ address }) => address); - - if (initiativesToCheck.length === 0) { - return { - bribeTokens: [], - claimableInitiatives: [], - totalBold: DNUM_0, - }; - } - - const [completedEpochs, userAllocations, bribeChecks] = await Promise.all([ - getLatestCompletedEpoch(currentEpoch), - getUserAllocationHistory(account), - readContracts(wagmiConfig, { - contracts: initiativesToCheck.map((initiative) => ({ - abi: BribeInitiative, - address: initiative, - functionName: "bribeToken", - } as const)), - allowFailure: true, - }), - ]); - - const bribeInitiatives: Array<{ - address: Address; - bribeToken: Address; - }> = []; - - for (const [index, token] of bribeChecks.entries()) { - const address = initiativesToCheck[index]?.toLowerCase() as Address | undefined; - if ( - address - && token.result - && userAllocations.find((allocation) => allocation.initiative === address && allocation.voteLQTY > 0n) - ) { - bribeInitiatives.push({ - address, - bribeToken: token.result, - }); - } - } - - if (bribeInitiatives.length === 0) { - return { - bribeTokens: [], - claimableInitiatives: [], - totalBold: DNUM_0, - }; - } - - // for each bribe initiative, check claimable epochs - const claimableInitiatives: BribeClaim["claimableInitiatives"] = []; - const bribeTokenData = new Map(); - - const bribeDetailsPerInitiative = await Promise.all( - bribeInitiatives.map(async ({ address, bribeToken }) => { - // no completed epochs yet - if (completedEpochs < 1) { - return null; - } - - const epochsToCheck = Math.min(completedEpochs, BRIBING_CHECK_EPOCH_LIMIT); - const startEpoch = Math.max(1, completedEpochs - epochsToCheck + 1); - const userAllocationsToInitiative = userAllocations.filter((allocation) => allocation.initiative === address); - - const [totalAllocationsToInitiative, results] = await Promise.all([ - getTotalAllocationHistory(address), - readContracts(wagmiConfig, { - contracts: Array.from({ length: epochsToCheck }, (_, index) => { - const BribeContract = { abi: BribeInitiative, address } as const; - const epoch = BigInt(startEpoch + index); - return [{ - ...BribeContract, - functionName: "claimedBribeAtEpoch", - args: [account, epoch], - }, { - ...BribeContract, - functionName: "bribeByEpoch", - args: [epoch], - }] as const; - }).flat(), - allowFailure: false, - }), - ]); - - const claimableEpochs: number[] = []; - const claimData: ClaimData[] = []; - let initiativeBold = DNUM_0; - let initiativeBribeToken = DNUM_0; - - // process results in groups of 2 (one per epoch) - for (let epochIndex = 0; epochIndex < epochsToCheck; epochIndex++) { - const epoch = startEpoch + epochIndex; - const resultIndex = epochIndex * 2; - - const hasClaimed = results[resultIndex] as boolean; - const [ - remainingBold, - remainingBribeToken, - claimedVotes, - ] = results[resultIndex + 1] as [bigint, bigint, bigint]; - - // allocations are ordered by descending epoch, - // so this finds the most recent one at the time of `epoch` - const userAllocation = userAllocationsToInitiative.find((allocation) => allocation.epoch <= epoch); - const totalAllocation = totalAllocationsToInitiative.find((allocation) => allocation.epoch <= epoch); - - // skip if already claimed or no bribes available - if ( - hasClaimed - || (remainingBold === 0n && remainingBribeToken === 0n) - || !totalAllocation - || !userAllocation || userAllocation.voteLQTY === 0n - ) { - continue; - } - - const epochEnd = govState.data.epochStart - - ((currentEpoch - BigInt(epoch)) * epochDuration) - + epochDuration; - - // voting power at the end of the epoch - const userVP = votingPower(userAllocation.voteLQTY, userAllocation.voteOffset, epochEnd); - const totalVP = votingPower(totalAllocation.voteLQTY, totalAllocation.voteOffset, epochEnd); - const remainingVP = totalVP - claimedVotes; - - if (remainingVP > 0n && userVP > 0n) { - const userShare = userVP <= remainingVP ? userVP : remainingVP; - const shareRatio = dn.div(dnum18(userShare), dnum18(remainingVP)); - - const boldClaim = dn.mul(dnum18(remainingBold), shareRatio); - const bribeTokenClaim = dn.mul(dnum18(remainingBribeToken), shareRatio); - - initiativeBold = dn.add(initiativeBold, boldClaim); - initiativeBribeToken = dn.add(initiativeBribeToken, bribeTokenClaim); - claimableEpochs.push(epoch); - claimData.push({ - epoch, - prevLQTYAllocationEpoch: Number(userAllocation.epoch), - prevTotalLQTYAllocationEpoch: Number(totalAllocation.epoch), - }); - } - } - - if (claimableEpochs.length === 0) { - return null; - } - - return { - boldAmount: initiativeBold, - bribeTokenAddress: bribeToken, - bribeTokenAmount: initiativeBribeToken, - epochs: claimableEpochs, - initiative: address, - claimData, - }; - }), - ); - - // filter out null results and prepare final data - let totalBold = DNUM_0; - for (const details of bribeDetailsPerInitiative) { - if (!details) continue; - claimableInitiatives.push(details); - bribeTokenData.set(details.bribeTokenAddress, { - amount: dn.add( - bribeTokenData.get(details.bribeTokenAddress)?.amount ?? DNUM_0, - details.bribeTokenAmount, - ), - }); - totalBold = dn.add(totalBold, details.boldAmount); - } - - // fetch token symbols for all bribe tokens - const tokenAddresses = Array.from(bribeTokenData.keys()); - if (tokenAddresses.length > 0) { - const symbols = await readContracts(wagmiConfig, { - contracts: tokenAddresses.map((tokenAddress) => ({ - abi: erc20Abi, - address: tokenAddress, - functionName: "symbol", - } as const)), - allowFailure: false, - }); - - for (const [index, symbol] of symbols.entries()) { - const tokenAddress = tokenAddresses[index]; - if (!tokenAddress) { - // should not happen since symbols is derived from tokenAddresses - throw new Error("Unexpected undefined token address in bribe token data"); - } - const current = bribeTokenData.get(tokenAddress); - if (current) { - bribeTokenData.set(tokenAddress, { ...current, symbol }); - } - } - } - - return { - bribeTokens: [...bribeTokenData.entries()].map( - ([address, { amount, symbol }]) => { - if (!symbol) { - throw new Error(`Failed to fetch symbol for token ${address}`); - } - return { address, symbol, amount }; - }, - ), - claimableInitiatives, - totalBold, - }; - }, - enabled: Boolean(account && govState.isSuccess && govUser.isSuccess), - }); + account; + throw new Error("undefined subgraph query"); } diff --git a/frontend/app/src/screens/StakeScreen/PanelStaking.tsx b/frontend/app/src/screens/StakeScreen/PanelStaking.tsx index 6b3fcefbe..32f7c64dd 100644 --- a/frontend/app/src/screens/StakeScreen/PanelStaking.tsx +++ b/frontend/app/src/screens/StakeScreen/PanelStaking.tsx @@ -6,7 +6,6 @@ import content from "@/src/content"; import { dnum18, DNUM_0, dnumMax } from "@/src/dnum-utils"; import { parseInputFloat } from "@/src/form-utils"; import { fmtnum } from "@/src/formatting"; -import { useGovernanceStats, useGovernanceUser } from "@/src/liquity-governance"; import { useStakePosition } from "@/src/liquity-utils"; import { usePrice } from "@/src/services/Prices"; import { infoTooltipProps } from "@/src/uikit-utils"; @@ -24,11 +23,8 @@ export function PanelStaking() { const [value, setValue] = useState(""); const [focused, setFocused] = useState(false); - const govStats = useGovernanceStats(); - const govUser = useGovernanceUser(account.address ?? null); - - const stakedLqty = dnum18(govUser.data?.stakedLQTY); - const totalStakedLqty = dnum18(govStats.data?.totalLQTYStaked); + const stakedLqty = dnum18(0n); + const totalStakedLqty = dnum18(0n); const stakePosition = useStakePosition(account.address ?? null); diff --git a/frontend/app/src/screens/StakeScreen/PanelVoting.tsx b/frontend/app/src/screens/StakeScreen/PanelVoting.tsx index 910c89412..978af6836 100644 --- a/frontend/app/src/screens/StakeScreen/PanelVoting.tsx +++ b/frontend/app/src/screens/StakeScreen/PanelVoting.tsx @@ -1,33 +1,24 @@ -import type { InitiativeStatus, VoteTotals } from "@/src/liquity-governance"; -import type { Address, Dnum, Entries, Initiative, Vote, VoteAllocation, VoteAllocations } from "@/src/types"; +import type { InitiativeStatus} from "@/src/liquity-governance"; +import type { Address, Dnum, Entries, VoteAllocations } from "@/src/types"; import { Amount } from "@/src/comps/Amount/Amount"; import { FlowButton } from "@/src/comps/FlowButton/FlowButton"; import { LinkTextButton } from "@/src/comps/LinkTextButton/LinkTextButton"; import { Spinner } from "@/src/comps/Spinner/Spinner"; import { Tag } from "@/src/comps/Tag/Tag"; -import { VoteInput } from "@/src/comps/VoteInput/VoteInput"; import content from "@/src/content"; -import { dnum18, DNUM_0 } from "@/src/dnum-utils"; -import { CHAIN_BLOCK_EXPLORER, CHAIN_ID } from "@/src/env"; -import { fmtnum, formatDate } from "@/src/formatting"; +import { formatDate } from "@/src/formatting"; import { - useCurrentEpochBribes, useGovernanceState, - useGovernanceUser, useInitiativesStates, useInitiativesVoteTotals, - useNamedInitiatives, votingPower, } from "@/src/liquity-governance"; -import { usePrice } from "@/src/services/Prices"; -import { tokenIconUrl } from "@/src/utils"; import { jsonStringifyWithBigInt } from "@/src/utils"; -import { useAccount } from "@/src/wagmi-utils"; import { css } from "@/styled-system/css"; -import { Button, IconDownvote, IconEdit, IconExternal, IconUpvote, shortenAddress, TokenIcon } from "@liquity2/uikit"; +import { IconExternal} from "@liquity2/uikit"; import * as dn from "dnum"; -import { useEffect, useMemo, useRef, useState } from "react"; +import { useEffect, useMemo, useState } from "react"; function isInitiativeStatusActive( status: InitiativeStatus, @@ -37,23 +28,6 @@ function isInitiativeStatusActive( && status !== "unregisterable" && status !== "warm up"; } - -function initiativeStatusLabel(status: InitiativeStatus) { - if (status === "skip" || status === "claimable" || status === "claimed") { - return "Active"; - } - if (status === "warm up") { - return "Warm-up period"; - } - if (status === "unregisterable") { - return "Unregistering"; - } - if (status === "disabled") { - return "Disabled"; - } - return ""; -} - function filterVoteAllocationsForSubmission( voteAllocations: VoteAllocations, initiativesStates: Record, @@ -78,20 +52,16 @@ function filterVoteAllocationsForSubmission( } export function PanelVoting() { - const account = useAccount(); const governanceState = useGovernanceState(); - const governanceUser = useGovernanceUser(account.address ?? null); - const initiatives = useNamedInitiatives(); - const initiativesAddresses = initiatives.data?.map((i) => i.address) ?? []; + const initiativesAddresses = new Array
(); const initiativesStates = useInitiativesStates(initiativesAddresses); - const currentBribes = useCurrentEpochBribes(initiativesAddresses); const voteTotals = useInitiativesVoteTotals(initiativesAddresses); - const stakedLQTY = governanceUser.data?.stakedLQTY; - const stakedOffset = governanceUser.data?.stakedOffset; + const stakedLQTY = 0n; + const stakedOffset = 0n; const epochEnd = governanceState.data?.epochEnd; - const absoluteAllocations = governanceUser.data?.allocations; + const absoluteAllocations = 0n; // current vote allocations const [voteAllocations, setVoteAllocations] = useState({}); @@ -117,36 +87,12 @@ export function PanelVoting() { const allocations: VoteAllocations = {}; - for (const allocation of absoluteAllocations) { - const vote = allocation.voteLQTY > 0n - ? "for" as const - : allocation.vetoLQTY > 0n - ? "against" as const - : null; - - if (vote === null) continue; - - // rounded to 4 decimals - const value = ( - BigInt(1e4) * ( - vote === "for" - ? votingPower(allocation.voteLQTY, allocation.voteOffset, epochEnd) - : votingPower(allocation.vetoLQTY, allocation.vetoOffset, epochEnd) - ) + stakedVotingPower / 2n - ) / stakedVotingPower; - - allocations[allocation.initiative] = { - vote, - value: [value, 4], - }; - } - setVoteAllocations(allocations); setInputVoteAllocations(allocations); }, [stakedLQTY, stakedOffset, epochEnd, jsonStringifyWithBigInt(absoluteAllocations)]); const hasAnyAllocationChange = useMemo(() => { - if (!governanceUser.data || !initiativesStates.data) { + if (!initiativesStates.data) { return false; } @@ -173,28 +119,12 @@ export function PanelVoting() { const isCutoff = governanceState.data?.period === "cutoff"; - const hasAnyAllocations = (governanceUser.data?.allocations ?? []).length > 0; + const hasAnyAllocations = false; const remainingVotingPower = useMemo(() => { let remaining = dn.from(1, 18); const combinedAllocations: Record = {}; - const stakedLQTY = governanceUser.data?.stakedLQTY ?? 0n; - const allocations = governanceUser.data?.allocations ?? []; - - // current allocations - if (stakedLQTY > 0n) { - for (const allocation of allocations) { - const currentVoteAmount = allocation.voteLQTY > 0n - ? allocation.voteLQTY - : allocation.vetoLQTY; - - if (currentVoteAmount > 0n) { - const proportion = dn.div([currentVoteAmount, 18], [stakedLQTY, 18]); - combinedAllocations[allocation.initiative] = proportion; - } - } - } // input allocations (takes precedence) for (const [address, voteData] of Object.entries(inputVoteAllocations) as Entries) { @@ -216,7 +146,7 @@ export function PanelVoting() { return remaining; }, [ - governanceUser.data, + [], inputVoteAllocations, initiativesStates.data, ]); @@ -230,26 +160,6 @@ export function PanelVoting() { ? rtf.format(Math.ceil(daysLeft * 24), "hours") : rtf.format(Math.ceil(daysLeft * 24 * 60), "minute"); - const handleVote = (initiativeAddress: Address, vote: Vote | null) => { - setInputVoteAllocations((prev) => ({ - ...prev, - [initiativeAddress]: { - vote: prev[initiativeAddress]?.vote === vote ? null : vote, - value: dn.from(0), - }, - })); - }; - - const handleVoteInputChange = (initiativeAddress: Address, value: Dnum) => { - setInputVoteAllocations((prev) => ({ - ...prev, - [initiativeAddress]: { - vote: prev[initiativeAddress]?.vote ?? null, - value: dn.div(value, 100), - }, - })); - }; - const allowSubmit = hasAnyAllocationChange && stakedLQTY && ( ( dn.eq(remainingVotingPower, 0) && hasAnyAllocations @@ -267,10 +177,8 @@ export function PanelVoting() { if ( governanceState.status !== "success" - || initiatives.status !== "success" || initiativesStates.status !== "success" || voteTotals.status !== "success" - || governanceUser.status !== "success" ) { return (
- {initiatives.data - // remove inactive initiatives that are not voted on - ?.filter((initiative) => ( - isInitiativeStatusActive( - initiativesStates.data?.[initiative.address]?.status ?? "nonexistent", - ) || Boolean( - voteAllocations[initiative.address], - ) - )) - .sort((a, b) => { - // 1. sort by allocation - const allocationA = voteAllocations[a.address]; - const allocationB = voteAllocations[b.address]; - if (allocationA && !allocationB) return -1; - if (!allocationA && allocationB) return 1; - - // 2. sort by status - const statusA = initiativesStates.data?.[a.address]?.status ?? "nonexistent"; - const statusB = initiativesStates.data?.[b.address]?.status ?? "nonexistent"; - const isActiveA = isInitiativeStatusActive(statusA); - const isActiveB = isInitiativeStatusActive(statusB); - if (isActiveA && !isActiveB) return -1; - if (!isActiveA && isActiveB) return 1; - - return 0; - }) - .map((initiative, index) => { - const status = initiativesStates.data?.[initiative.address]?.status; - return ( - - ); - })} @@ -708,386 +572,6 @@ export function PanelVoting() { ); } - -function calculateVotesPct( - governanceState?: { countedVoteLQTY: bigint; countedVoteOffset: bigint; epochEnd: bigint }, - initiativeState?: VoteTotals, -) { - if (!governanceState || !initiativeState) return null; - - const totalVotingPower = votingPower( - governanceState.countedVoteLQTY, - governanceState.countedVoteOffset, - governanceState.epochEnd, - ); - - if (totalVotingPower === 0n) return DNUM_0; - - const initiativeVotingPower = votingPower( - initiativeState.voteLQTY, - initiativeState.voteOffset, - governanceState.epochEnd, - ); - - return dn.div(dnum18(initiativeVotingPower), dnum18(totalVotingPower)); -} - -function InitiativeRow({ - bribe, - disableFor, - disabled, - initiative, - initiativesStatus, - inputVoteAllocation, - onVote, - onVoteInputChange, - voteAllocation, - voteTotals, -}: { - bribe?: { - boldAmount: Dnum; - tokenAmount: Dnum; - tokenAddress: Address; - tokenSymbol: string; - }; - disableFor: boolean; - disabled: boolean; - initiative: Initiative; - initiativesStatus?: InitiativeStatus; - inputVoteAllocation?: VoteAllocations[Address]; - onVote: (initiative: Address, vote: Vote) => void; - onVoteInputChange: (initiative: Address, value: Dnum) => void; - voteAllocation?: VoteAllocation; - voteTotals?: VoteTotals; -}) { - const inputRef = useRef(null); - const [editIntent, setEditIntent] = useState(false); - const editMode = (editIntent || !voteAllocation?.vote) && !disabled; - const boldPrice = usePrice(bribe ? "BOLD" : null); - const bribeTokenPrice = usePrice(bribe ? bribe.tokenSymbol : null); - const governanceState = useGovernanceState(); - const votesPct = calculateVotesPct(governanceState.data, voteTotals); - - return ( - - -
-
-
- {initiative.url - ? ( - - {initiative.name ?? "Initiative"} - - - } - /> - ) - : ( - initiative.name ?? "Initiative" - )} -
- {initiativesStatus && ( -
- {initiativeStatusLabel(initiativesStatus)} -
- )} -
-
- -
- -
- Votes: - -
- - {bribe && (dn.gt(bribe.boldAmount, 0) || dn.gt(bribe.tokenAmount, 0)) && ( -
- Bribing: -
- {dn.gt(bribe.boldAmount, 0) && ( -
- - - {boldPrice.data && ( - - )} -
- )} - {dn.gt(bribe.tokenAmount, 0) && ( -
- - - {bribeTokenPrice.data && ( - - )} -
- )} -
-
- )} -
- - -
- {editMode - ? ( - { - onVoteInputChange(initiative.address, value); - }} - onVote={(vote) => { - onVote(initiative.address, vote); - }} - value={inputVoteAllocation?.value ?? null} - vote={inputVoteAllocation?.vote ?? null} - /> - ) - : voteAllocation?.vote - ? ( - { - setEditIntent(true); - setTimeout(() => { - inputRef.current?.focus(); - }, 0); - }} - disabled={disabled} - share={voteAllocation.value} - vote={voteAllocation.vote} - /> - ) - : ( - {}} - onVote={() => {}} - value={null} - vote={null} - /> - )} -
- - - ); -} - -function Vote({ - onEdit, - disabled, - share, - vote, -}: { - onEdit?: () => void; - disabled: boolean; - share: Dnum; - vote: Vote; -}) { - return ( -
-
-
- {vote === "for" && } - {vote === "against" && ( -
- -
- )} -
- {fmtnum(share, { preset: "pct2", suffix: "%" })} -
-
-
-
- ); -} - function BribeMarketsInfo() { return (
)} diff --git a/frontend/app/src/subgraph.ts b/frontend/app/src/subgraph.ts index 4d1849b9e..b338ed925 100644 --- a/frontend/app/src/subgraph.ts +++ b/frontend/app/src/subgraph.ts @@ -250,98 +250,3 @@ export async function getAllInterestRateBrackets() { .sort((a, b) => dn.cmp(a.rate, b.rate)); } -const GovernanceGlobalDataQuery = graphql(` - query GovernanceGlobalData { - governanceInitiatives { - id - } - - governanceVotingPower(id: "total") { - allocatedLQTY - allocatedOffset - unallocatedLQTY - unallocatedOffset - } - } -`); - -// get all the registered initiatives and total voting power -export async function getGovernanceGlobalData() { - const { governanceInitiatives, governanceVotingPower } = await graphQuery(GovernanceGlobalDataQuery); - return { - registeredInitiatives: governanceInitiatives.map((initiative) => initiative.id as Address), - - totalVotingPower: { - allocatedLQTY: BigInt(governanceVotingPower?.allocatedLQTY ?? 0), - allocatedOffset: BigInt(governanceVotingPower?.allocatedOffset ?? 0), - unallocatedLQTY: BigInt(governanceVotingPower?.unallocatedLQTY ?? 0), - unallocatedOffset: BigInt(governanceVotingPower?.unallocatedOffset ?? 0), - }, - }; -} - -const UserAllocationHistoryQuery = graphql(` - query UserAllocationHistory($user: String) { - governanceAllocations( - where: { user: $user } - orderBy: epoch - orderDirection: desc - first: 1000 - ) { - epoch - initiative { id } - voteLQTY - vetoLQTY - voteOffset - vetoOffset - } - } -`); - -const TotalAllocationHistoryQuery = graphql(` - query TotalAllocationHistory($initiative: String) { - governanceAllocations( - where: { initiative: $initiative, user: null } - orderBy: epoch - orderDirection: desc - first: 1000 - ) { - epoch - voteLQTY - vetoLQTY - voteOffset - vetoOffset - } - } -`); - -// A user's allocation history ordered by descending epoch -export async function getUserAllocationHistoryFromSubgraph(user: Address) { - const { governanceAllocations } = await graphQuery(UserAllocationHistoryQuery, { - user: user.toLowerCase(), - }); - - return governanceAllocations.map((allocation) => ({ - epoch: Number(allocation.epoch), - initiative: allocation.initiative.id, - voteLQTY: BigInt(allocation.voteLQTY), - vetoLQTY: BigInt(allocation.vetoLQTY), - voteOffset: BigInt(allocation.voteOffset), - vetoOffset: BigInt(allocation.vetoOffset), - })); -} - -// An initiative's total allocation history ordered by descending epoch -export async function getTotalAllocationHistoryFromSubgraph(initiative: Address) { - const { governanceAllocations } = await graphQuery(TotalAllocationHistoryQuery, { - initiative: initiative.toLowerCase(), - }); - - return governanceAllocations.map((allocation) => ({ - epoch: Number(allocation.epoch), - voteLQTY: BigInt(allocation.voteLQTY), - vetoLQTY: BigInt(allocation.vetoLQTY), - voteOffset: BigInt(allocation.voteOffset), - vetoOffset: BigInt(allocation.vetoOffset), - })); -} diff --git a/frontend/app/src/tx-flows/allocateVotingPower.tsx b/frontend/app/src/tx-flows/allocateVotingPower.tsx index 06b95abc7..fd1cfe890 100644 --- a/frontend/app/src/tx-flows/allocateVotingPower.tsx +++ b/frontend/app/src/tx-flows/allocateVotingPower.tsx @@ -5,7 +5,7 @@ import { AddressLink } from "@/src/comps/AddressLink/AddressLink"; import { Amount } from "@/src/comps/Amount/Amount"; import { GAS_ALLOCATE_LQTY_MIN_HEADROOM } from "@/src/constants"; import { getUserAllocatedInitiatives } from "@/src/liquity-governance"; -import { getUserStates, useGovernanceUser, useNamedInitiatives } from "@/src/liquity-governance"; +import { getUserStates } from "@/src/liquity-governance"; import { TransactionDetailsRow } from "@/src/screens/TransactionsScreen/TransactionsScreen"; import { TransactionStatus } from "@/src/screens/TransactionsScreen/TransactionStatus"; import { vVoteAllocations } from "@/src/valibot-utils"; @@ -28,8 +28,8 @@ export const allocateVotingPower: FlowDeclaration = title: "Review & Send Transaction", Summary({ request, account }) { - const governanceUser = useGovernanceUser(account); - const stakedLqty: Dnum = [governanceUser.data?.stakedLQTY ?? 0n, 18]; + account; + const stakedLqty: Dnum = [0n, 18]; let totalLqtyAllocation: Dnum = [0n, 18]; for (const vote of Object.values(request.voteAllocations)) { @@ -150,9 +150,8 @@ export const allocateVotingPower: FlowDeclaration = }, Details({ request, account }) { - const initiatives = useNamedInitiatives(); - const governanceUser = useGovernanceUser(account); - const stakedLQTY = governanceUser.data?.stakedLQTY ?? 0n; + account; + const stakedLQTY = 0n; const allocations = Object.entries(request.voteAllocations); if (allocations.length === 0) { return ( @@ -165,7 +164,7 @@ export const allocateVotingPower: FlowDeclaration = ); } return allocations.map(([address, vote]) => { - const initiative = initiatives.data?.find((i) => i.address === address); + const initiative = false; return !initiative || !vote ? null : ( = { const { Governance } = ctx.contracts; const inputs: `0x${string}`[] = []; - const allocatedInitiatives = await getUserAllocatedInitiatives( - ctx.wagmiConfig, - ctx.account, - ); - - // reset allocations if the user has any - if (allocatedInitiatives.length > 0) { - inputs.push(encodeFunctionData({ - abi: Governance.abi, - functionName: "resetAllocations", - args: [allocatedInitiatives, true], - })); - } - // withdraw LQTY inputs.push(encodeFunctionData({ abi: Governance.abi, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7dc6b904e..2c5415b2c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -359,6 +359,9 @@ importers: '@graphprotocol/graph-ts': specifier: ^0.38.0 version: 0.38.1 + pnpm: + specifier: ^10.15.0 + version: 10.15.0 tsx: specifier: ^4.19.4 version: 4.20.3 @@ -16986,6 +16989,12 @@ packages: engines: {node: '>=10.13.0'} dev: false + /pnpm@10.15.0: + resolution: {integrity: sha512-SG68JZ0+mZpOhpHOA7XKxKccvso5Nyqbdiy1AM/fCHPiyxar49lRse4s8BJQPwJ7mLZYTk3yJSTgx0UNnseqew==} + engines: {node: '>=18.12'} + hasBin: true + dev: false + /pony-cause@2.1.11: resolution: {integrity: sha512-M7LhCsdNbNgiLYiP4WjsfLUuFmCfnjdF6jKe2R9NKl4WFN+HZPGHJZ9lnLP7f9ZnKe3U9nuWD0szirmj+migUg==} engines: {node: '>=12.0.0'} diff --git a/subgraph/networks.json b/subgraph/networks.json index b24d2abfd..04ec42d61 100644 --- a/subgraph/networks.json +++ b/subgraph/networks.json @@ -2,29 +2,24 @@ "local": { "BoldToken": { "address": "0x0e18b884ec3095f7c27bbbeb0a266a5674bcaffd" - }, - "Governance": { - "address": "0x79fdb65c20e75f8961d54f6714d2fcc4c30d1073" } }, "mainnet": { "BoldToken": { "address": "0x6440f144b7e50d6a8439336510312d2f54beb01d", "startBlock": 22483043 - }, - "Governance": { - "address": "0x807def5e7d057df05c796f4bc75c3fe82bd6eee1", - "startBlock": 22496547 } }, "sepolia": { "BoldToken": { "address": "0x181dff47198bf3f3ed65877332e8395eb6817c4c", "startBlock": 8316063 - }, - "Governance": { - "address": "0xf68db4e851d89daf0fb842b01f75d94e0cb44f49", - "startBlock": 8316191 + } + }, + "neura-testnet": { + "BoldToken": { + "address": "0xc13441f42e0aca71ea246aba87bdcdf646a456dd", + "startBlock": 100000 } } } diff --git a/subgraph/package.json b/subgraph/package.json index 58f271daa..99064e9ef 100644 --- a/subgraph/package.json +++ b/subgraph/package.json @@ -11,6 +11,7 @@ }, "dependencies": { "@graphprotocol/graph-ts": "^0.38.0", + "pnpm": "^10.15.0", "tsx": "^4.19.4", "zx": "^8.5.3" } diff --git a/subgraph/schema.graphql b/subgraph/schema.graphql index ce8e82df3..1ab1fa1a5 100644 --- a/subgraph/schema.graphql +++ b/subgraph/schema.graphql @@ -74,34 +74,3 @@ type InterestBatch @entity(immutable: false) { updatedAt: BigInt! troves: [Trove!]! @derivedFrom(field: "interestBatch") } - -type GovernanceVotingPower @entity(immutable: false) { - id: ID! # userAddress, e.g. "0x0000000000000000000000000000000000000000", or "total" - allocatedLQTY: BigInt! - allocatedOffset: BigInt! - unallocatedLQTY: BigInt! - unallocatedOffset: BigInt! -} - -type GovernanceAllocationIndex @entity(immutable: false) { - id: ID! # "userAddress:initiativeAddress" or "initiativeAddress" - user: String - initiative: GovernanceInitiative! - latestAllocation: GovernanceAllocation! -} - -type GovernanceAllocation @entity(immutable: false) { - id: ID! # "userAddress:initiativeAddress:epoch" or "initiativeAddress:epoch" - user: String - initiative: GovernanceInitiative! - epoch: BigInt! - voteLQTY: BigInt! - vetoLQTY: BigInt! - voteOffset: BigInt! - vetoOffset: BigInt! -} - -type GovernanceInitiative @entity(immutable: false) { - id: ID! # "initiativeAddress", e.g. "0x0000000000000000000000000000000000000000" - registered: Boolean! -} diff --git a/subgraph/src/Governance.mapping.ts b/subgraph/src/Governance.mapping.ts deleted file mode 100644 index b4ffb1df3..000000000 --- a/subgraph/src/Governance.mapping.ts +++ /dev/null @@ -1,201 +0,0 @@ -import { BigInt } from "@graphprotocol/graph-ts"; -import { - AllocateLQTY as AllocateLQTYEvent, - DepositLQTY as DepositLQTYEvent, - RegisterInitiative as RegisterInitiativeEvent, - UnregisterInitiative as UnregisterInitiativeEvent, - WithdrawLQTY as WithdrawLQTYEvent, -} from "../generated/Governance/Governance"; -import { - GovernanceAllocation, - GovernanceAllocationIndex, - GovernanceInitiative, - GovernanceVotingPower, -} from "../generated/schema"; - -export function handleRegisterInitiative(event: RegisterInitiativeEvent): void { - let initiative = new GovernanceInitiative(event.params.initiative.toHex()); - initiative.registered = true; - initiative.save(); -} - -export function handleUnregisterInitiative(event: UnregisterInitiativeEvent): void { - let initiative = GovernanceInitiative.load(event.params.initiative.toHex()); - if (initiative === null) { - throw new Error("UnregisterInitiative event for non-existing initiative"); - } - initiative.registered = false; - initiative.save(); -} - -function getVotingPower(id: string): GovernanceVotingPower { - let votingPower = GovernanceVotingPower.load(id); - - if (votingPower === null) { - votingPower = new GovernanceVotingPower(id); - votingPower.allocatedLQTY = BigInt.zero(); - votingPower.allocatedOffset = BigInt.zero(); - votingPower.unallocatedLQTY = BigInt.zero(); - votingPower.unallocatedOffset = BigInt.zero(); - } - - return votingPower; -} - -export function handleDepositLQTY(event: DepositLQTYEvent): void { - let userVotingPower = getVotingPower(event.params.user.toHex()); - let toteVotingPower = getVotingPower("total"); - - let offsetIncrease = event.params.lqtyAmount.times(event.block.timestamp); - userVotingPower.unallocatedLQTY = userVotingPower.unallocatedLQTY.plus(event.params.lqtyAmount); - toteVotingPower.unallocatedLQTY = toteVotingPower.unallocatedLQTY.plus(event.params.lqtyAmount); - userVotingPower.unallocatedOffset = userVotingPower.unallocatedOffset.plus(offsetIncrease); - toteVotingPower.unallocatedOffset = toteVotingPower.unallocatedOffset.plus(offsetIncrease); - - userVotingPower.save(); - toteVotingPower.save(); -} - -export function handleWithdrawLQTY(event: WithdrawLQTYEvent): void { - let userVotingPower = getVotingPower(event.params.user.toHex()); - let toteVotingPower = getVotingPower("total"); - - let offsetDecrease = userVotingPower.unallocatedLQTY.notEqual(BigInt.zero()) - ? userVotingPower.unallocatedOffset - .times(event.params.lqtyReceived) - .div(userVotingPower.unallocatedLQTY) - : BigInt.zero(); - - userVotingPower.unallocatedLQTY = userVotingPower.unallocatedLQTY.minus(event.params.lqtyReceived); - toteVotingPower.unallocatedLQTY = toteVotingPower.unallocatedLQTY.minus(event.params.lqtyReceived); - userVotingPower.unallocatedOffset = userVotingPower.unallocatedOffset.minus(offsetDecrease); - toteVotingPower.unallocatedOffset = toteVotingPower.unallocatedOffset.minus(offsetDecrease); - - userVotingPower.save(); - toteVotingPower.save(); -} - -class GovernanceAllocationAndIndex { - allocation: GovernanceAllocation; - allocationIndex: GovernanceAllocationIndex | null; - - constructor(allocation: GovernanceAllocation, allocationIndex: GovernanceAllocationIndex | null) { - this.allocation = allocation; - this.allocationIndex = allocationIndex; - } - - save(): void { - this.allocation.save(); - - // Workaround for AssemblyScript compiler being stupid - let allocationIndex = this.allocationIndex; - if (allocationIndex !== null) allocationIndex.save(); - } -} - -function getAllocation( - userId: string | null, - initiativeId: string, - epoch: BigInt, -): GovernanceAllocationAndIndex { - let allocationIndexId = userId !== null ? userId + ":" + initiativeId : initiativeId; - let allocationIndex: GovernanceAllocationIndex | null = null; - let allocationId = allocationIndexId + ":" + epoch.toString(); - let allocation = GovernanceAllocation.load(allocationId); - - if (allocation === null) { - allocation = new GovernanceAllocation(allocationId); - allocation.user = userId; - allocation.initiative = initiativeId; - allocation.epoch = epoch; - - allocationIndex = GovernanceAllocationIndex.load(allocationIndexId); - if (allocationIndex === null) { - allocationIndex = new GovernanceAllocationIndex(allocationIndexId); - allocationIndex.user = userId; - allocationIndex.initiative = initiativeId; - - allocation.voteLQTY = BigInt.zero(); - allocation.vetoLQTY = BigInt.zero(); - allocation.voteOffset = BigInt.zero(); - allocation.vetoOffset = BigInt.zero(); - } else { - let prevAllocation = GovernanceAllocation.load(allocationIndex.latestAllocation); - if (prevAllocation === null) { - throw new Error("GovernanceAllocation not found: " + allocationIndex.latestAllocation); - } - - allocation.voteLQTY = prevAllocation.voteLQTY; - allocation.vetoLQTY = prevAllocation.vetoLQTY; - allocation.voteOffset = prevAllocation.voteOffset; - allocation.vetoOffset = prevAllocation.vetoOffset; - } - - allocationIndex.latestAllocation = allocationId; - } - - return new GovernanceAllocationAndIndex(allocation, allocationIndex); -} - -export function handleAllocateLQTY(event: AllocateLQTYEvent): void { - let userId = event.params.user.toHex(); - let initiativeId = event.params.initiative.toHex(); - - let userVotingPower = getVotingPower(userId); - let toteVotingPower = getVotingPower("total"); - - let user = getAllocation(userId, initiativeId, event.params.atEpoch); - let tote = getAllocation(null, initiativeId, event.params.atEpoch); - - let deltaVoteOffset = event.params.deltaVoteLQTY.gt(BigInt.zero()) - ? (userVotingPower.unallocatedLQTY.notEqual(BigInt.zero()) - ? userVotingPower.unallocatedOffset.times(event.params.deltaVoteLQTY).div(userVotingPower.unallocatedLQTY) - : BigInt.zero()) - : (user.allocation.voteLQTY.notEqual(BigInt.zero()) - ? user.allocation.voteOffset.times(event.params.deltaVoteLQTY).div(user.allocation.voteLQTY) - : BigInt.zero()); - - let deltaVetoOffset = event.params.deltaVetoLQTY.gt(BigInt.zero()) - ? (userVotingPower.unallocatedLQTY.notEqual(BigInt.zero()) - ? userVotingPower.unallocatedOffset.times(event.params.deltaVetoLQTY).div(userVotingPower.unallocatedLQTY) - : BigInt.zero()) - : (user.allocation.vetoLQTY.notEqual(BigInt.zero()) - ? user.allocation.vetoOffset.times(event.params.deltaVetoLQTY).div(user.allocation.vetoLQTY) - : BigInt.zero()); - - user.allocation.voteLQTY = user.allocation.voteLQTY.plus(event.params.deltaVoteLQTY); - tote.allocation.voteLQTY = tote.allocation.voteLQTY.plus(event.params.deltaVoteLQTY); - user.allocation.vetoLQTY = user.allocation.vetoLQTY.plus(event.params.deltaVetoLQTY); - tote.allocation.vetoLQTY = tote.allocation.vetoLQTY.plus(event.params.deltaVetoLQTY); - - userVotingPower.allocatedLQTY = userVotingPower.allocatedLQTY.plus(event.params.deltaVoteLQTY); - toteVotingPower.allocatedLQTY = toteVotingPower.allocatedLQTY.plus(event.params.deltaVoteLQTY); - userVotingPower.allocatedLQTY = userVotingPower.allocatedLQTY.plus(event.params.deltaVetoLQTY); - toteVotingPower.allocatedLQTY = toteVotingPower.allocatedLQTY.plus(event.params.deltaVetoLQTY); - - userVotingPower.unallocatedLQTY = userVotingPower.unallocatedLQTY.minus(event.params.deltaVoteLQTY); - toteVotingPower.unallocatedLQTY = toteVotingPower.unallocatedLQTY.minus(event.params.deltaVoteLQTY); - userVotingPower.unallocatedLQTY = userVotingPower.unallocatedLQTY.minus(event.params.deltaVetoLQTY); - toteVotingPower.unallocatedLQTY = toteVotingPower.unallocatedLQTY.minus(event.params.deltaVetoLQTY); - - user.allocation.voteOffset = user.allocation.voteOffset.plus(deltaVoteOffset); - tote.allocation.voteOffset = tote.allocation.voteOffset.plus(deltaVoteOffset); - user.allocation.vetoOffset = user.allocation.vetoOffset.plus(deltaVetoOffset); - tote.allocation.vetoOffset = tote.allocation.vetoOffset.plus(deltaVetoOffset); - - userVotingPower.allocatedOffset = userVotingPower.allocatedOffset.plus(deltaVoteOffset); - toteVotingPower.allocatedOffset = toteVotingPower.allocatedOffset.plus(deltaVoteOffset); - userVotingPower.allocatedOffset = userVotingPower.allocatedOffset.plus(deltaVetoOffset); - toteVotingPower.allocatedOffset = toteVotingPower.allocatedOffset.plus(deltaVetoOffset); - - userVotingPower.unallocatedOffset = userVotingPower.unallocatedOffset.minus(deltaVoteOffset); - toteVotingPower.unallocatedOffset = toteVotingPower.unallocatedOffset.minus(deltaVoteOffset); - userVotingPower.unallocatedOffset = userVotingPower.unallocatedOffset.minus(deltaVetoOffset); - toteVotingPower.unallocatedOffset = toteVotingPower.unallocatedOffset.minus(deltaVetoOffset); - - userVotingPower.save(); - toteVotingPower.save(); - - user.save(); - tote.save(); -} diff --git a/subgraph/subgraph.yaml b/subgraph/subgraph.yaml index 18c7458e2..9d1708167 100644 --- a/subgraph/subgraph.yaml +++ b/subgraph/subgraph.yaml @@ -6,8 +6,8 @@ dataSources: name: BoldToken source: abi: BoldToken - address: "0x6440f144b7e50d6a8439336510312d2f54beb01d" - startBlock: 22483043 + address: "0xc13441f42e0aca71ea246aba87bdcdf646a456dd" + startBlock: 100000 mapping: kind: ethereum/events apiVersion: 0.0.9 @@ -32,41 +32,11 @@ dataSources: - event: CollateralRegistryAddressChanged(address) handler: handleCollateralRegistryAddressChanged file: ./src/BoldToken.mapping.ts - network: mainnet - - kind: ethereum/contract - name: Governance - source: - abi: Governance - address: "0x807def5e7d057df05c796f4bc75c3fe82bd6eee1" - startBlock: 22496547 - mapping: - kind: ethereum/events - apiVersion: 0.0.9 - language: wasm/assemblyscript - entities: - - GovernanceAllocation - - GovernanceInitiative - - GovernanceUser - abis: - - name: Governance - file: ../contracts/out/Governance.sol/Governance.json - eventHandlers: - - event: DepositLQTY(indexed - address,address,uint256,uint256,uint256,uint256,uint256) - handler: handleDepositLQTY - - event: WithdrawLQTY(indexed - address,address,uint256,uint256,uint256,uint256,uint256,uint256) - handler: handleWithdrawLQTY - - event: AllocateLQTY(indexed address,indexed address,int256,int256,uint256,uint8) - handler: handleAllocateLQTY - - event: RegisterInitiative(address,address,uint256,uint8) - handler: handleRegisterInitiative - file: ./src/Governance.mapping.ts - network: mainnet + network: neura-testnet templates: - name: TroveManager kind: ethereum/contract - network: mainnet + network: neura-testnet source: abi: TroveManager mapping: @@ -102,7 +72,7 @@ templates: handler: handleBatchUpdated - name: TroveNFT kind: ethereum/contract - network: mainnet + network: neura-testnet source: abi: TroveNFT mapping: