Skip to content

Commit

Permalink
fix: patch github provider
Browse files Browse the repository at this point in the history
  • Loading branch information
sakulstra committed Jun 5, 2024
1 parent 1905cc4 commit 84d30a1
Show file tree
Hide file tree
Showing 13 changed files with 132 additions and 93 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ Therefore applications usually go either:
- "fully centralized"

Applications around aave governance exist on both sides of the spectrum, but there's currently no agnostic solution that fits both needs.
To close this gap `@bgd-labs/aave-v3-governance-cache`(temporary name) offers a common interface and a variety of adapters for interfaces to go their own way.
To close this gap `@bgd-labs/aave-v3-governance-cache`(temporary name) offers a common interface and a variety of provider for interfaces to go their own way.

## Adapters
## Providers

### Local Cache

The `localCache` is a simple file based cache that fetches "new" data based on the last seen block and stores them in json files per proposal.
The `customStorageProvider` is a simple file based cache that fetches "new" data based on the last seen block and stores them in json files per proposal.
If no cache is found the cache will try to refresh automatically.

```
Expand Down
16 changes: 10 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@bgd-labs/aave-v3-governance-cache",
"version": "1.0.1",
"version": "1.0.2",
"sideEffects": false,
"files": [
"cache",
Expand All @@ -17,12 +17,16 @@
"default": "./dist/index.js"
},
"./localCache": {
"types": "./dist/localCache.d.ts",
"default": "./dist/adapter/localCache.js"
"types": "./dist/customStorageProvider.d.ts",
"default": "./dist/providers/customStorageProvider.js"
},
"./githubHybrid": {
"types": "./dist/githubHybrid.d.ts",
"default": "./dist/adapter/githubHybrid.js"
"./github": {
"types": "./dist/githubPagesProvider.d.ts",
"default": "./dist/providers/githubPagesProvider.js"
},
"./fallbackProvider": {
"types": "./dist/fallbackProvider.d.ts",
"default": "./dist/providers/fallbackProvider.js"
},
"./refreshCache": {
"types": "./dist/refreshCache.d.ts",
Expand Down
8 changes: 5 additions & 3 deletions scripts/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ import dts from 'bun-plugin-dts';
await Bun.build({
entrypoints: [
'src/index.ts',
'src/adapter/localCache.ts',
'src/adapter/noCache.ts',
'src/adapter/githubHybrid.ts',
'src/providers/customStorageProvider.ts',
'src/providers/storage/fileSystem.ts',
'src/providers/rpcProvider.ts',
'src/providers/fallbackProvider.ts',
'src/providers/githubPagesProvider.ts',
'src/common/refreshCache.ts',
],
outdir: './dist',
Expand Down
8 changes: 5 additions & 3 deletions scripts/refreshCache.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import {githubHybridCacheAdapter} from '../src/adapter/githubHybrid';
import {localCacheAdapter} from '../src/adapter/localCache';
import {customStorageProvider} from '../src/providers/customStorageProvider';
import {refreshCache} from '../src/common/refreshCache';
import {fileSystemStorage} from '../dist/fileSystem';

refreshCache(githubHybridCacheAdapter(localCacheAdapter));
const provider = customStorageProvider(fileSystemStorage);

refreshCache(provider);
42 changes: 0 additions & 42 deletions src/adapter/githubHybrid.ts

This file was deleted.

4 changes: 2 additions & 2 deletions src/common/refreshCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ import {
GovernanceV3Scroll,
GovernanceV3Base,
} from '@bgd-labs/aave-address-book';
import type {GovernanceCacheAdapter} from '..';
import type {GovernanceCacheAdapterWithSync} from '..';

export async function refreshCache(adapter: GovernanceCacheAdapter) {
export async function refreshCache(adapter: GovernanceCacheAdapterWithSync) {
await adapter.syncProposalCache({
chainId: 1,
governance: GovernanceV3Ethereum.GOVERNANCE,
Expand Down
2 changes: 2 additions & 0 deletions src/errors.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const ISSUES_FETCHING_PAYLOAD = 'ISSUES_FETCHING_PAYLOAD';
export const ISSUES_FETCHING_PROPOSAL = 'ISSUES_FETCHING_PROPOSAL';
7 changes: 5 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,6 @@ export interface GetProposalReturnType {
}

export interface GovernanceCacheAdapter {
syncPayloadsCache: (args: {chainId: number; payloadsController: Address}) => any;
syncProposalCache: (args: {chainId: number; governance: Address}) => any;
getPayload: (args: {
chainId: number;
payloadsController: Address;
Expand All @@ -60,6 +58,11 @@ export interface GovernanceCacheAdapter {
}) => GetProposalReturnType | Promise<GetProposalReturnType>;
}

export interface GovernanceCacheAdapterWithSync extends GovernanceCacheAdapter {
syncPayloadsCache: (args: {chainId: number; payloadsController: Address}) => any;
syncProposalCache: (args: {chainId: number; governance: Address}) => any;
}

/**
* Proposal types
*/
Expand Down
31 changes: 31 additions & 0 deletions src/providers/customStorageProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import {type GovernanceCacheAdapterWithSync} from '..';
import {ISSUES_FETCHING_PAYLOAD, ISSUES_FETCHING_PROPOSAL} from '../errors';

export const customStorageProvider = (
adapter: GovernanceCacheAdapterWithSync,
): GovernanceCacheAdapterWithSync => ({
async getPayload(args) {
let cache = await adapter.getPayload(args);
if (!cache) {
await adapter.syncPayloadsCache(args);
cache = await adapter.getPayload(args);
if (!cache) throw new Error(ISSUES_FETCHING_PAYLOAD);
}
return cache;
},
async getProposal(args) {
let cache = await adapter.getProposal(args);
if (!cache) {
await adapter.syncProposalCache(args);
cache = await adapter.getProposal(args);
if (!cache) throw new Error(ISSUES_FETCHING_PROPOSAL);
}
return cache;
},
syncPayloadsCache(args) {
return adapter.syncPayloadsCache(args);
},
syncProposalCache(args) {
return adapter.syncProposalCache(args);
},
});
29 changes: 29 additions & 0 deletions src/providers/fallbackProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import type {GovernanceCacheAdapter} from '..';
import {ISSUES_FETCHING_PAYLOAD, ISSUES_FETCHING_PROPOSAL} from '../errors';

export const fallbackProvider = <T extends GovernanceCacheAdapter>(
...providers: T[]
): GovernanceCacheAdapter => ({
async getPayload(args) {
for (let i = 0; i < providers.length; i++) {
try {
const response = providers[i].getPayload(args);
return response;
} catch (e) {
console.log('falling back to next provider');
}
}
throw new Error(ISSUES_FETCHING_PAYLOAD);
},
async getProposal(args) {
for (let i = 0; i < providers.length; i++) {
try {
const response = await providers[i].getProposal(args);
return response;
} catch (e) {
console.log('falling back to next provider');
}
}
throw new Error(ISSUES_FETCHING_PROPOSAL);
},
});
25 changes: 25 additions & 0 deletions src/providers/githubPagesProvider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* Hybrid adapter that tries to fetch via github pages
* If github pages doesn't contain the desired data it will fallback to the supplied adapter
*/
import type {GovernanceCacheAdapter, PayloadCacheRaw, ProposalCacheRaw} from '..';
import {formatPayloadLogs} from '../common/payloadsController';
import {formatProposalLogs} from '../common/governance';

function getPath() {
return 'https://bgd-labs.github.io/v3-governance-cache/cache/';
}

export const githubPagesCacheAdapter: GovernanceCacheAdapter = {
async getPayload({chainId, payloadsController, payloadId}) {
const path = `${chainId.toString()}/${payloadsController}/payloads/${payloadId}.json`;
const cache = (await (await fetch(getPath() + path)).json()) as PayloadCacheRaw;
return {payload: cache.payload!, logs: formatPayloadLogs(cache.events)};
},
async getProposal({chainId, governance, proposalId}) {
const path = `${chainId.toString()}/${governance}/proposals/${proposalId}.json`;
console.log(path);
const cache = (await (await fetch(getPath() + path)).json()) as ProposalCacheRaw;
return {proposal: cache.proposal!, logs: formatProposalLogs(cache.events), ipfs: cache.ipfs!};
},
};
8 changes: 1 addition & 7 deletions src/adapter/noCache.ts → src/providers/rpcProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type {GovernanceCacheAdapter} from '..';
import {getPayload} from '../common/payloadsController';
import {getProposal} from '../common/governance';

export const noCacheAdapter: GovernanceCacheAdapter = {
export const rpcProvider: GovernanceCacheAdapter = {
async getPayload({chainId, payloadsController, payloadId}) {
const client = CHAIN_ID_CLIENT_MAP[chainId];
return {payload: await getPayload({client, payloadsController, payloadId}), logs: {} as any};
Expand All @@ -18,10 +18,4 @@ export const noCacheAdapter: GovernanceCacheAdapter = {
const proposal = await getProposal({client, proposalId, governance});
return {proposal, logs: {} as any, ipfs: await getProposalMetadata(proposal.ipfsHash)};
},
syncPayloadsCache() {
throw new Error('syncing is not available on the "no-cache" adapter');
},
syncProposalCache() {
throw new Error('syncing is not available on the "no-cache" adapter');
},
};
39 changes: 14 additions & 25 deletions src/adapter/localCache.ts → src/providers/storage/fileSystem.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,21 @@
/**
* Cache adapter which simply stores the ache in a local cache directory
*/
import {existsSync, readFileSync, mkdirSync, writeFileSync} from 'fs';
import path from 'path';
import {CHAIN_ID_CLIENT_MAP, getProposalMetadata} from '@bgd-labs/js-utils';
import packageJson from '../../package.json';
import packageJson from '../../../package.json';
import {
isPayloadFinal,
isProposalFinal,
type GovernanceCacheAdapter,
type GovernanceCacheAdapterWithSync,
type PayloadCacheRaw,
type ProposalCacheRaw,
} from '..';
import {formatProposalLogs, getProposal, syncGovernanceEvents} from '../common/governance';
} from '../..';
import {ISSUES_FETCHING_PAYLOAD, ISSUES_FETCHING_PROPOSAL} from '../../errors';
import {
formatPayloadLogs,
getPayload,
syncPayloadsControllerEvents,
} from '../common/payloadsController';
} from '../../common/payloadsController';
import {formatProposalLogs, syncGovernanceEvents, getProposal} from '../../common/governance';
import {CHAIN_ID_CLIENT_MAP, getProposalMetadata} from '@bgd-labs/js-utils';

function getPath() {
const installPath = path.join(process.cwd(), 'node_modules', packageJson.name);
Expand Down Expand Up @@ -63,7 +61,7 @@ export type TrackingCache = {lastSeenBlock: string | bigint; isFinal: Record<str
* 1. fetches new events
* 2. re-fetches the proposal for ever proposalId encountered in the events
*/
const syncProposalCache: GovernanceCacheAdapter['syncProposalCache'] = async ({
const syncProposalCache: GovernanceCacheAdapterWithSync['syncProposalCache'] = async ({
chainId,
governance,
}) => {
Expand Down Expand Up @@ -124,7 +122,7 @@ const syncProposalCache: GovernanceCacheAdapter['syncProposalCache'] = async ({
* 1. fetch new events
* 2. fetch all payloads encountered in the events
*/
const syncPayloadsCache: GovernanceCacheAdapter['syncPayloadsCache'] = async ({
const syncPayloadsCache: GovernanceCacheAdapterWithSync['syncPayloadsCache'] = async ({
chainId,
payloadsController,
}) => {
Expand Down Expand Up @@ -169,26 +167,17 @@ const syncPayloadsCache: GovernanceCacheAdapter['syncPayloadsCache'] = async ({
return newData;
};

export const localCacheAdapter: GovernanceCacheAdapter = {
export const fileSystemStorage: GovernanceCacheAdapterWithSync = {
async getPayload({chainId, payloadsController, payloadId}) {
const path = `${chainId.toString()}/${payloadsController}/payloads`;
let cache = readJSONCache<PayloadCacheRaw>(path, payloadId);
if (!cache) {
await syncPayloadsCache({chainId, payloadsController});
cache = readJSONCache<PayloadCacheRaw>(path, payloadId);
if (!cache)
throw new Error(`Payload ${payloadId} not found on ${chainId}:${payloadsController}`);
}
const cache = readJSONCache<PayloadCacheRaw>(path, payloadId);
if (!cache) throw new Error(ISSUES_FETCHING_PAYLOAD);
return {payload: cache.payload!, logs: formatPayloadLogs(cache.events)};
},
async getProposal({chainId, governance, proposalId}) {
const path = `${chainId.toString()}/${governance}/proposals`;
let cache = readJSONCache<ProposalCacheRaw>(path, proposalId);
if (!cache) {
await syncProposalCache({chainId, governance});
cache = readJSONCache<ProposalCacheRaw>(path, proposalId);
if (!cache) throw new Error(`Payload ${proposalId} not found on ${chainId}:${governance}`);
}
const cache = readJSONCache<ProposalCacheRaw>(path, proposalId);
if (!cache) throw new Error(ISSUES_FETCHING_PROPOSAL);
return {proposal: cache.proposal!, logs: formatProposalLogs(cache.events), ipfs: cache.ipfs!};
},
syncPayloadsCache,
Expand Down

0 comments on commit 84d30a1

Please sign in to comment.