Skip to content

Commit

Permalink
cleanup: caching (#124)
Browse files Browse the repository at this point in the history
* fix: remove useless caching

* fix: patch caching

* fix: more cleanups

* fix: fetch ir strategies
  • Loading branch information
sakulstra authored Mar 24, 2024
1 parent f9d38fd commit 9499074
Show file tree
Hide file tree
Showing 8 changed files with 34 additions and 101 deletions.
15 changes: 3 additions & 12 deletions src/commands/governance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,7 @@ import { toAddressLink, toTxLink } from '../govv3/utils/markdownUtils';
import { getAccountRPL, getBlockRLP } from '../govv3/proofs';
import { DEFAULT_GOVERNANCE, DEFAULT_GOVERNANCE_CLIENT, FORMAT } from '../utils/constants';
import { getPayloadsController } from '../govv3/payloadsController';
import {
cacheGovernance,
cachePayloadsController,
readBookKeepingCache,
writeBookKeepingCache,
} from '../govv3/cache/updateCache';
import { cacheGovernance, cachePayloadsController } from '../govv3/cache/updateCache';
import { findPayloadsController } from '../govv3/utils/checkAddress';
import { generateReport } from '../govv3/generatePayloadReport';

Expand Down Expand Up @@ -51,9 +46,7 @@ export function addCommand(program: Command) {
const client = CHAIN_ID_CLIENT_MAP[Number(chainId) as keyof typeof CHAIN_ID_CLIENT_MAP];
const payloadsControllerAddress = findPayloadsController(Number(chainId));
const payloadsController = getPayloadsController(payloadsControllerAddress as Hex, client);
const cache = readBookKeepingCache();
const { eventsCache } = await cachePayloadsController(client, payloadsControllerAddress as Address, cache);
writeBookKeepingCache(cache);
const { eventsCache } = await cachePayloadsController(client, payloadsControllerAddress as Address);
const config = await payloadsController.getPayload(payloadId, eventsCache);
const result = await payloadsController.simulatePayloadExecutionOnTenderly(Number(payloadId), config);
console.log(
Expand All @@ -75,9 +68,7 @@ export function addCommand(program: Command) {
client: DEFAULT_GOVERNANCE_CLIENT,
blockCreated: 9640498n,
});
const cache = readBookKeepingCache();
const { eventsCache } = await cacheGovernance(DEFAULT_GOVERNANCE_CLIENT, DEFAULT_GOVERNANCE, cache);
writeBookKeepingCache(cache);
const { eventsCache } = await cacheGovernance(DEFAULT_GOVERNANCE_CLIENT, DEFAULT_GOVERNANCE);
const count = await governance.governanceContract.read.getProposalsCount();
const proposalIds = [...Array(Number(count)).keys()].reverse();
const selectedProposalId = BigInt(
Expand Down
15 changes: 0 additions & 15 deletions src/govv3/cache/modules/governance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,6 @@ export type ProposalVotingActivatedEvent = LogWithTimestamp<
ExtractAbiEvent<typeof IGovernanceCore_ABI, 'VotingActivated'>
>;

export enum ProposalState {
Null, // proposal does not exists
Created, // created, waiting for a cooldown to initiate the balances snapshot
Active, // balances snapshot set, voting in progress
Queued, // voting results submitted, but proposal is under grace period when guardian can cancel it
Executed, // results sent to the execution chain(s)
Failed, // voting was not successful
Cancelled, // got cancelled by guardian, or because proposition power of creator dropped below allowed minimum
Expired,
}

export function isProposalFinal(state: ProposalState) {
return [ProposalState.Executed, ProposalState.Failed, ProposalState.Cancelled, ProposalState.Expired].includes(state);
}

export async function getGovernanceEvents(
governanceAddress: Address,
client: Client,
Expand Down
19 changes: 1 addition & 18 deletions src/govv3/cache/modules/payloadsController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Address, Client, getAbiItem } from 'viem';
import { getBlock } from 'viem/actions';
import type { ExtractAbiEvent } from 'abitype';
import { LogWithTimestamp } from '../../../utils/logs';
import { PayloadState } from '../../payloadsController';

export type PayloadCreatedEvent = LogWithTimestamp<
ExtractAbiEvent<typeof IPayloadsControllerCore_ABI, 'PayloadCreated'>
Expand All @@ -13,24 +14,6 @@ export type PayloadExecutedEvent = LogWithTimestamp<
ExtractAbiEvent<typeof IPayloadsControllerCore_ABI, 'PayloadExecuted'>
>;

export enum PayloadState {
None,
Created,
Queued,
Executed,
Cancelled,
Expired,
}

export const HUMAN_READABLE_PAYLOAD_STATE = {
[PayloadState.None]: 'None',
[PayloadState.Created]: 'Created',
[PayloadState.Queued]: 'Queued',
[PayloadState.Executed]: 'Executed',
[PayloadState.Cancelled]: 'Cancelled',
[PayloadState.Expired]: 'Expired',
};

export function isPayloadFinal(state: number) {
return [
PayloadState.Cancelled,
Expand Down
64 changes: 22 additions & 42 deletions src/govv3/cache/updateCache.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,24 @@
import {
CHAIN_ID_CLIENT_MAP,
ProposalMetadata,
getBlockAtTimestamp,
getProposalMetadata,
readJSONCache,
writeJSONCache,
} from '@bgd-labs/js-utils';
import { getGovernanceEvents, isProposalFinal } from './modules/governance';
import { CHAIN_ID_CLIENT_MAP, getBlockAtTimestamp, readJSONCache, writeJSONCache } from '@bgd-labs/js-utils';
import { getGovernanceEvents } from './modules/governance';
import { getPayloadsControllerEvents, isPayloadFinal } from './modules/payloadsController';
import { AbiStateMutability, Address, Client, ContractFunctionReturnType, getContract } from 'viem';
import { IGovernanceCore_ABI, IPayloadsControllerCore_ABI } from '@bgd-labs/aave-address-book';
import { getBlockNumber } from 'viem/actions';
import { isProposalFinal } from '../governance';

export async function cacheGovernance(
client: Client,
governanceAddress: Address,
bookKeepingCache: BookKeepingCache
governanceAddress: Address
): Promise<{
proposalsCache: Record<
string,
ContractFunctionReturnType<typeof IGovernanceCore_ABI, AbiStateMutability, 'getProposal'>
>;
eventsCache: Awaited<ReturnType<typeof getGovernanceEvents>>;
}> {
const bookKeepingCacheId = 'governance';
const proposalsPath = `${client.chain!.id.toString()}/proposals`;
const cachedBlock: { lastSeenBlock: string } =
readJSONCache<{ lastSeenBlock: number }>(proposalsPath, 'lastSeenBlock') || {};
const currentBlockOnGovernanceChain = await getBlockNumber(client);
const contract = getContract({
abi: IGovernanceCore_ABI,
Expand All @@ -32,14 +27,13 @@ export async function cacheGovernance(
});
const proposalsCount = await contract.read.getProposalsCount();
if (proposalsCount == BigInt(0)) {
bookKeepingCache[bookKeepingCacheId] = currentBlockOnGovernanceChain.toString();
cachedBlock.lastSeenBlock = currentBlockOnGovernanceChain.toString();
return {
proposalsCache: {},
eventsCache: [],
};
}
// cache data
const proposalsPath = `${client.chain!.id.toString()}/proposals`;
const proposalsCache =
readJSONCache<
Record<string, ContractFunctionReturnType<typeof IGovernanceCore_ABI, AbiStateMutability, 'getProposal'>>
Expand All @@ -56,8 +50,8 @@ export async function cacheGovernance(
const eventsPath = `${client.chain!.id.toString()}/events`;
const governanceEvents =
readJSONCache<Awaited<ReturnType<typeof getGovernanceEvents>>>(eventsPath, governanceAddress) || [];
const lastSeenBlock = bookKeepingCache[bookKeepingCacheId]
? BigInt(bookKeepingCache[bookKeepingCacheId])
const lastSeenBlock = cachedBlock.lastSeenBlock
? BigInt(cachedBlock.lastSeenBlock)
: (
await getBlockAtTimestamp({
client: client,
Expand All @@ -74,17 +68,16 @@ export async function cacheGovernance(
currentBlockOnGovernanceChain
);
const eventsCache = [...governanceEvents, ...logs];
cachedBlock.lastSeenBlock = currentBlockOnGovernanceChain.toString();
writeJSONCache(proposalsPath, 'lastSeenBlock', cachedBlock);
writeJSONCache(eventsPath, governanceAddress, eventsCache);
bookKeepingCache[bookKeepingCacheId] = currentBlockOnGovernanceChain.toString();
return { proposalsCache, eventsCache };
}

export async function cachePayloadsController(
client: Client,
payloadsControllerAddress: Address,
bookKeepingCache: BookKeepingCache
) {
export async function cachePayloadsController(client: Client, payloadsControllerAddress: Address) {
const payloadsPath = `${client.chain!.id}/payloads`;
const cachedBlock: { lastSeenBlock: string } =
readJSONCache<{ lastSeenBlock: number }>(payloadsPath, 'lastSeenBlock') || {};
const contract = getContract({
abi: IPayloadsControllerCore_ABI,
client,
Expand All @@ -94,7 +87,7 @@ export async function cachePayloadsController(

const currentBlockOnPayloadsControllerChain = await getBlockNumber(client);
if (payloadsCount == 0) {
bookKeepingCache[payloadsPath] = currentBlockOnPayloadsControllerChain.toString();
cachedBlock.lastSeenBlock = currentBlockOnPayloadsControllerChain.toString();
return { eventsCache: [] };
}
// cache data
Expand All @@ -116,8 +109,8 @@ export async function cachePayloadsController(
const eventsPath = `${client.chain!.id}/events`;
const eventsCache =
readJSONCache<Awaited<ReturnType<typeof getPayloadsControllerEvents>>>(eventsPath, payloadsControllerAddress) || [];
const lastSeenBlock = bookKeepingCache[payloadsPath]
? BigInt(bookKeepingCache[payloadsPath])
const lastSeenBlock = cachedBlock
? BigInt(cachedBlock.lastSeenBlock)
: (
await getBlockAtTimestamp({
client: client,
Expand All @@ -134,29 +127,16 @@ export async function cachePayloadsController(
currentBlockOnPayloadsControllerChain
);
const updatedEventsCache = [...eventsCache, ...logs];
cachedBlock.lastSeenBlock = currentBlockOnPayloadsControllerChain.toString();
writeJSONCache(eventsPath, payloadsControllerAddress, updatedEventsCache);
bookKeepingCache[payloadsPath] = currentBlockOnPayloadsControllerChain.toString();
writeJSONCache(payloadsPath, 'lastSeenBlock', cachedBlock);
return { eventsCache: updatedEventsCache };
}

export async function cachePayloadsControllers(controllers: Map<Address, number>, bookKeepingCache: BookKeepingCache) {
export async function cachePayloadsControllers(controllers: Map<Address, number>) {
return await Promise.all(
Array.from(controllers).map(async ([address, chainId]) =>
cachePayloadsController(CHAIN_ID_CLIENT_MAP[chainId], address, bookKeepingCache)
cachePayloadsController(CHAIN_ID_CLIENT_MAP[chainId], address)
)
);
}

/**
* simple cache mapping:
* filename:blockNumber with the last used block for caching
*/
type BookKeepingCache = Record<string, string>;

export function readBookKeepingCache() {
return readJSONCache<BookKeepingCache>('bookKeeping', 'lastFetchedBlocks') || {};
}

export function writeBookKeepingCache(cache: BookKeepingCache) {
writeJSONCache('bookKeeping', 'lastFetchedBlocks', cache);
}
11 changes: 2 additions & 9 deletions src/govv3/governance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import { setBits } from '../utils/storageSlots';
import { VOTING_SLOTS, WAREHOUSE_SLOTS, getAccountRPL, getProof } from './proofs';
import { logInfo } from '../utils/logger';
import { GetProofReturnType } from 'viem/_types/actions/public/getProof';
import { readJSONCache, writeJSONCache } from '@bgd-labs/js-utils';
import {
ProposalCreatedEvent,
ProposalExecutedEvent,
Expand All @@ -50,7 +49,7 @@ export enum ProposalState {
Expired,
}

function isStateFinal(state: ProposalState) {
export function isProposalFinal(state: ProposalState) {
return [ProposalState.Executed, ProposalState.Failed, ProposalState.Cancelled, ProposalState.Expired].includes(state);
}

Expand Down Expand Up @@ -124,13 +123,7 @@ export const getGovernance = ({ address, client }: GetGovernanceParams): Governa
});

async function getProposal(proposalId: bigint) {
const filePath = client.chain!.id.toString() + `/proposals`;
const fileName = proposalId;
const cache = readJSONCache(filePath, fileName.toString());
if (cache) return cache;
const proposal = await governanceContract.read.getProposal([proposalId]);
if (isStateFinal(proposal.state)) writeJSONCache(filePath, fileName.toString(), proposal);
return proposal;
return governanceContract.read.getProposal([proposalId]);
}

async function getSimulationPayloadForExecution(proposalId: bigint) {
Expand Down
7 changes: 3 additions & 4 deletions src/govv3/simulate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { PayloadsController, getPayloadsController } from './payloadsController'
import { CHAIN_ID_CLIENT_MAP } from '@bgd-labs/js-utils';
import { generateReport } from './generatePayloadReport';
import { generateProposalReport } from './generateProposalReport';
import { cacheGovernance, cachePayloadsController, readBookKeepingCache } from './cache/updateCache';
import { cacheGovernance, cachePayloadsController } from './cache/updateCache';

/**
* Reference implementation, unused
Expand All @@ -16,10 +16,9 @@ import { cacheGovernance, cachePayloadsController, readBookKeepingCache } from '
* @returns
*/
export async function simulateProposal(governanceAddress: Hex, client: Client, proposalId: bigint) {
const cache = readBookKeepingCache();
logInfo('General', `Running simulation for ${proposalId}`);
const governance = getGovernance({ address: governanceAddress, client });
const { eventsCache } = await cacheGovernance(client, governanceAddress, cache);
const { eventsCache } = await cacheGovernance(client, governanceAddress);
const proposal = await governance.getProposalAndLogs(proposalId, eventsCache);
const result = await governance.simulateProposalExecutionOnTenderly(proposalId, proposal);
console.log(
Expand All @@ -37,7 +36,7 @@ export async function simulateProposal(governanceAddress: Hex, client: Client, p
for (const payload of proposal.proposal.payloads) {
const client = CHAIN_ID_CLIENT_MAP[Number(payload.chain) as keyof typeof CHAIN_ID_CLIENT_MAP];
const controllerContract = getPayloadsController(payload.payloadsController, client);
const { eventsCache } = await cachePayloadsController(client, payload.payloadsController, cache);
const { eventsCache } = await cachePayloadsController(client, payload.payloadsController);
const config = await controllerContract.getPayload(payload.payloadId, eventsCache);
try {
const result = await controllerContract.simulatePayloadExecutionOnTenderly(payload.payloadId, config);
Expand Down
2 changes: 2 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@ export * from './govv3/generateProposalReport';
export * from './utils/tenderlyClient';
export * from './utils/logger';
export * from './govv3/cache/updateCache';
export * from './govv3/cache/modules/governance';
export * from './govv3/cache/modules/payloadsController';
export * from './govv3/utils/checkAddress';
2 changes: 1 addition & 1 deletion src/reports/fetch-IR-strategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export async function fetchRateStrategyImage(rate: AaveV3Strategy) {
};
const searchParams = new URLSearchParams(paramsObj);
const writeStream = createWriteStream(pathWithFile);
const { body } = await fetch(`https://bgdash.vercel.app/api/static?${searchParams.toString()}`);
const { body } = await fetch(`https://dash.onaave.com/api/static?${searchParams.toString()}`);
if (!body) throw Error('Error fetching the image');
await finished(Readable.fromWeb(body as any).pipe(writeStream));
}

0 comments on commit 9499074

Please sign in to comment.