GovernanceV3Service.ts
1 import { 2 AaveTokenV3Service, 3 AccessLevel, 4 ChainId, 5 GovernanceCoreService, 6 GovernanceDataHelperService, 7 GovernancePowerType, 8 Payload, 9 PayloadsDataHelperService, 10 } from '@aave/contract-helpers'; 11 import { BigNumber } from 'ethers'; 12 import { formatUnits } from 'ethers/lib/utils'; 13 import { governanceV3Config } from 'src/ui-config/governanceConfig'; 14 import { getProvider } from 'src/utils/marketsAndNetworksConfig'; 15 16 export type PayloadParams = { 17 payloadControllerAddress: string; 18 payloadId: number; 19 chainId: ChainId; 20 }; 21 22 type PayloadData = { 23 [key in ChainId]: { 24 [payloadsControllerAddres: string]: number[]; 25 }; 26 }; 27 28 export type EnhancedPayload = Payload & { 29 chainId: number; 30 }; 31 32 export class GovernanceV3Service { 33 private getDataHelperService() { 34 const provider = getProvider(governanceV3Config.coreChainId); 35 return new GovernanceDataHelperService( 36 governanceV3Config.addresses.GOVERNANCE_DATA_HELPER, 37 provider 38 ); 39 } 40 41 private getCoreService() { 42 const provider = getProvider(governanceV3Config.coreChainId); 43 return new GovernanceCoreService(governanceV3Config.addresses.GOVERNANCE_CORE, provider); 44 } 45 46 private getPayloadDataHelperService(chainId: ChainId) { 47 const provider = getProvider(chainId); 48 const payload = new PayloadsDataHelperService( 49 governanceV3Config.payloadsControllerDataHelpers[chainId], 50 provider 51 ); 52 return payload; 53 } 54 55 async getProposalsData(from = 0, to = 0, limit = 10) { 56 const dataHelperService = this.getDataHelperService(); 57 const proposals = await dataHelperService.getProposalsData( 58 governanceV3Config.addresses.GOVERNANCE_CORE, 59 from, 60 to, 61 limit 62 ); 63 return proposals; 64 } 65 66 async getVotingConfig() { 67 const dataHelperService = this.getDataHelperService(); 68 const votingConfig = await dataHelperService.getConstants( 69 governanceV3Config.addresses.GOVERNANCE_CORE, 70 [AccessLevel.Short_Executor, AccessLevel.Long_Executor] 71 ); 72 return votingConfig; 73 } 74 75 async getProposalCount() { 76 const coreService = this.getCoreService(); 77 return coreService.getProposalCount(); 78 } 79 80 async getRepresentationData(user: string) { 81 const dataHelperService = this.getDataHelperService(); 82 const representationData = await dataHelperService.getRepresentationData( 83 governanceV3Config.addresses.GOVERNANCE_CORE, 84 user, 85 [...governanceV3Config.votingChainIds] 86 ); 87 return representationData; 88 } 89 90 updateRepresentativesForChain( 91 user: string, 92 representatives: Array<{ chainId: ChainId; representative: string }> 93 ) { 94 const coreService = this.getCoreService(); 95 return coreService.updateRepresentativesForChain(user, representatives); 96 } 97 98 async getVotingPowerAt(blockHash: string, user: string, votingAssets: string[]) { 99 const provider = getProvider(governanceV3Config.coreChainId); 100 const block = await provider.getBlock(blockHash); 101 102 const tokenServices = votingAssets.map((token) => { 103 return { 104 asset: token, 105 service: new AaveTokenV3Service(token, provider), 106 }; 107 }); 108 const result = await Promise.all( 109 tokenServices.map( 110 async (s) => (await s.service.getPowerAt(block.number, user, GovernancePowerType.VOTING))[0] 111 ) 112 ); 113 const totalPower = result.reduce((acum, elem) => acum.add(elem), BigNumber.from(0)); 114 return formatUnits(totalPower, 18); 115 } 116 117 async getPayloadsData(payloadsControllerAddress: string, payloadIds: number[], chainId: ChainId) { 118 const dataHelperService = this.getPayloadDataHelperService(chainId); 119 const payloadsData = await dataHelperService.getPayloadsData( 120 payloadsControllerAddress, 121 payloadIds 122 ); 123 return payloadsData; 124 } 125 126 async getMultiChainPayloadsData(params: PayloadParams[]) { 127 const payloadsByChainId: PayloadData = params.reduce( 128 (acc, { chainId, payloadControllerAddress, payloadId }) => { 129 if (!acc[chainId]) { 130 acc[chainId] = {}; 131 } 132 133 if (!acc[chainId][payloadControllerAddress]) { 134 acc[chainId][payloadControllerAddress] = []; 135 } 136 137 acc[chainId][payloadControllerAddress].push(payloadId); 138 return acc; 139 }, 140 {} as PayloadData 141 ); 142 143 const promises: Promise<EnhancedPayload[]>[] = []; 144 Object.entries(payloadsByChainId).forEach(([chainId, payloads]) => { 145 const chainIdKey = +chainId; 146 Object.entries(payloads).forEach(([payloadControllerAddress, payloadIds]) => { 147 promises.push( 148 this.getPayloadsData(payloadControllerAddress, payloadIds, chainIdKey).then((data) => 149 data.map((payload) => ({ ...payload, chainId: chainIdKey })) 150 ) 151 ); 152 }); 153 }); 154 155 const data = await Promise.all(promises); 156 return data.flat(); 157 } 158 }