diff --git a/app/proposal/page.page.tsx b/app/proposal/page.page.tsx
index dc402c15..b7a8354a 100644
--- a/app/proposal/page.page.tsx
+++ b/app/proposal/page.page.tsx
@@ -2,7 +2,6 @@ import { IGovernanceCore_ABI } from '@bgd-labs/aave-address-book';
import {
CachedDetails,
getGovCoreConfigs,
- getProposalMetadata,
getProposalState,
getVotingMachineProposalState,
ProposalMetadata,
@@ -23,6 +22,7 @@ import {
cachedVotesPath,
githubStartUrl,
} from '../../src/utils/cacheGithubLinks';
+import { getProposalMetadata } from '../../src/utils/getProposalMetadata';
import { initialClients } from '../../src/utils/initialClients';
export const revalidate = 0;
@@ -44,7 +44,7 @@ export async function generateMetadata({
if (ipfsHash && proposalId) {
try {
- const ipfsData = await getProposalMetadata(ipfsHash);
+ const ipfsData = await getProposalMetadata({ hash: ipfsHash });
return {
title: `${metaTexts.main}${metaTexts.proposalId(proposalId)}`,
@@ -197,7 +197,7 @@ export default async function ProposalPage({
try {
ipfsDataSSR =
cachedDetailsData?.ipfs ??
- (ipfsHash ? await getProposalMetadata(ipfsHash) : undefined);
+ (ipfsHash ? await getProposalMetadata({ hash: ipfsHash }) : undefined);
} catch (e) {
ipfsDataSSR = cachedDetailsData?.ipfs;
}
diff --git a/package.json b/package.json
index 52f88ad5..5e38ba3c 100644
--- a/package.json
+++ b/package.json
@@ -32,7 +32,7 @@
},
"dependencies": {
"@bgd-labs/aave-address-book": "^2.26.0",
- "@bgd-labs/aave-governance-ui-helpers": "^3.1.3",
+ "@bgd-labs/aave-governance-ui-helpers": "^3.1.5",
"@bgd-labs/frontend-web3-utils": "^1.2.1",
"@emotion/cache": "^11.11.0",
"@emotion/react": "^11.11.4",
diff --git a/src/proposals/components/proposalList/ActiveProposalListItem.tsx b/src/proposals/components/proposalList/ActiveProposalListItem.tsx
index c38297dc..d5861415 100644
--- a/src/proposals/components/proposalList/ActiveProposalListItem.tsx
+++ b/src/proposals/components/proposalList/ActiveProposalListItem.tsx
@@ -6,7 +6,7 @@ import {
import { WalletType } from '@bgd-labs/frontend-web3-utils';
import { Box, useTheme } from '@mui/system';
import React, { useEffect, useState } from 'react';
-import { Hex, zeroAddress } from 'viem';
+import { zeroAddress } from 'viem';
import { useStore } from '../../../store/ZustandStoreProvider';
import { Link } from '../../../ui';
@@ -44,7 +44,6 @@ export function ActiveProposalListItem({
const appClients = useStore((state) => state.appClients);
const ipfsDataErrors = useStore((state) => state.ipfsDataErrors);
const ipfsData = useStore((state) => state.ipfsData);
- const getIpfsData = useStore((state) => state.getIpfsData);
let activeWallet = useStore((state) => state.activeWallet);
const proposal = proposalData.proposal;
@@ -55,22 +54,13 @@ export function ActiveProposalListItem({
const [isIPFSError, setIsIpfsError] = useState(
ipfsDataErrors[proposal.data.ipfsHash] && !ipfsData[proposal.data.ipfsHash],
);
- const [ipfsErrorCount, setIpfsErrorCount] = useState(0);
-
- const MAX_COUNT = 5;
useEffect(() => {
setIsIpfsError(
ipfsDataErrors[proposal.data.ipfsHash] &&
!ipfsData[proposal.data.ipfsHash],
);
- if (isIPFSError && ipfsErrorCount <= MAX_COUNT) {
- setTimeout(async () => {
- getIpfsData([proposal.data.id], proposal.data.ipfsHash as Hex);
- setIpfsErrorCount(ipfsErrorCount + 1);
- }, 1000);
- }
- }, [ipfsErrorCount, isIPFSError, Object.keys(ipfsDataErrors).length]);
+ }, [isIPFSError, Object.keys(ipfsDataErrors).length]);
if (isForHelpModal) {
activeWallet = {
@@ -214,7 +204,7 @@ export function ActiveProposalListItem({
? `${theme.palette.$text} !important`
: theme.palette.$text,
}}>
- {isIPFSError && ipfsErrorCount > MAX_COUNT ? (
+ {isIPFSError ? (
'Ipfs getting error'
) : isIPFSError ? (
diff --git a/src/proposals/store/proposalsSlice.ts b/src/proposals/store/proposalsSlice.ts
index c5a7434f..b1511191 100644
--- a/src/proposals/store/proposalsSlice.ts
+++ b/src/proposals/store/proposalsSlice.ts
@@ -4,7 +4,6 @@ import {
checkHash,
ContractsConstants,
getProofOfRepresentative,
- getProposalMetadata,
getProposalStepsAndAmounts,
getVotingMachineProposalState,
getVotingProofs,
@@ -38,7 +37,7 @@ import {
import { IUISlice } from '../../ui/store/uiSlice';
import { texts } from '../../ui/utils/texts';
import { appConfig } from '../../utils/appConfig';
-import { ipfsGateway } from '../../utils/configs';
+import { getProposalMetadata } from '../../utils/getProposalMetadata';
import { PAGE_SIZE } from '../../web3/services/govDataService';
import { ICreationFeesSlice } from '../../web3/store/creationFeesSlice';
import { ENSDataExists } from '../../web3/store/ensSelectors';
@@ -513,12 +512,10 @@ export const createProposalsSlice: StoreSlice<
filteredNewIpfsHashes.map(async (hash) => {
try {
- const ipfsData = await getProposalMetadata(
+ const ipfsData = await getProposalMetadata({
hash,
- ipfsGateway,
- get().setIpfsDataErrors,
- texts.other.fetchFromIpfsIncorrectHash,
- );
+ setIpfsError: get().setIpfsDataErrors,
+ });
if (ipfsData) {
get().setIpfsDataErrors(hash, '', true);
diff --git a/src/utils/cacheGithubLinks.ts b/src/utils/cacheGithubLinks.ts
index 123a6230..08c37363 100644
--- a/src/utils/cacheGithubLinks.ts
+++ b/src/utils/cacheGithubLinks.ts
@@ -1,6 +1,8 @@
import { coreName } from './appConfig';
-export const githubStartUrl = `https://raw.githubusercontent.com/bgd-labs/aave-governance-ui-helpers/main/cache/ui/${coreName}`;
+export const githubInitialUrl =
+ 'https://raw.githubusercontent.com/bgd-labs/aave-governance-ui-helpers/main/cache';
+export const githubStartUrl = `${githubInitialUrl}/ui/${coreName}`;
export const listViewPath = '/list_view_proposals.json';
export const cachedProposalsIdsPath = '/cached_proposals_ids.json';
@@ -15,3 +17,6 @@ export const cachedVotesPath = (id: number) =>
export const cachedEventsPath = (id: number) =>
`/events/proposal_${id}_events.json`;
+
+export const cachedIPFSDataPath = (ipfsHash: string) =>
+ `/ipfs/${ipfsHash}.json`;
diff --git a/src/utils/configs.ts b/src/utils/configs.ts
index 7ce09cc2..3d30e9bd 100644
--- a/src/utils/configs.ts
+++ b/src/utils/configs.ts
@@ -4,5 +4,11 @@ import { CHAINS } from './chains';
// ipfs gateway to get proposals metadata
export const ipfsGateway = 'https://cloudflare-ipfs.com/ipfs';
+export const fallbackGateways = [
+ 'https://ipfs.io',
+ 'https://ipfs.eth.aragon.network',
+ 'https://dweb.link',
+ 'https://ipfs.runfission.com',
+];
export const chainInfoHelper = initChainInformationConfig(CHAINS);
diff --git a/src/utils/getProposalMetadata.ts b/src/utils/getProposalMetadata.ts
new file mode 100644
index 00000000..77c1caa0
--- /dev/null
+++ b/src/utils/getProposalMetadata.ts
@@ -0,0 +1,53 @@
+import {
+ getProposalMetadata as baseGetProposalMetadata,
+ ProposalMetadata,
+} from '@bgd-labs/aave-governance-ui-helpers';
+import matter from 'gray-matter';
+
+import { texts } from '../ui/utils/texts';
+import { cachedIPFSDataPath, githubStartUrl } from './cacheGithubLinks';
+import { fallbackGateways, ipfsGateway } from './configs';
+
+export async function getProposalMetadata({
+ hash,
+ setIpfsError,
+}: {
+ hash: string;
+ setIpfsError?: (ipfsHash: string, text?: string, remove?: boolean) => void;
+}): Promise {
+ try {
+ const request = await fetch(`${githubStartUrl}${cachedIPFSDataPath(hash)}`);
+ if (request.ok) {
+ const response = await request.json();
+ const { content, data } = matter(response.description);
+ return {
+ ...response,
+ ipfsHash: hash,
+ description: content,
+ ...data,
+ };
+ } else {
+ console.error(
+ "Can't fetch cached ipfs data. Try to fetch from IPFS gateway",
+ );
+ return await baseGetProposalMetadata({
+ hash,
+ gateway: ipfsGateway,
+ setIpfsError,
+ errorText: texts.other.fetchFromIpfsError,
+ fallbackGateways,
+ });
+ }
+ } catch (e) {
+ console.error(
+ 'An error occurred while fetching proposal metadata from IPFS, trying to request one more time.',
+ );
+ return await baseGetProposalMetadata({
+ hash,
+ gateway: ipfsGateway,
+ setIpfsError,
+ errorText: texts.other.fetchFromIpfsError,
+ fallbackGateways,
+ });
+ }
+}
diff --git a/yarn.lock b/yarn.lock
index 4015d154..fbeed352 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1383,10 +1383,10 @@
resolved "https://registry.yarnpkg.com/@bgd-labs/aave-address-book/-/aave-address-book-2.26.0.tgz#d861386eb1fbc977a82c7f1c1ce4c1e6c30e77d0"
integrity sha512-1VjBruXMHEpPr7X6/m9XZH0fIxfNr2FgEvzhzCLb7Fb5opYU+4yTr7C+ATmQGGoy2I4PYDMr0kH6TMg3EpfvTw==
-"@bgd-labs/aave-governance-ui-helpers@^3.1.3":
- version "3.1.3"
- resolved "https://registry.yarnpkg.com/@bgd-labs/aave-governance-ui-helpers/-/aave-governance-ui-helpers-3.1.3.tgz#aada6c1e043ca3e12097bcdd7d59ec1e396f6519"
- integrity sha512-RiO46hwoz13309RqqQXKrxy/U+Ybb8DBYckKbZwiV7gXhbmBf2Hz6TRU78JsGPOMz0UUA7CRrb6V1c1OS48wqw==
+"@bgd-labs/aave-governance-ui-helpers@^3.1.5":
+ version "3.1.5"
+ resolved "https://registry.yarnpkg.com/@bgd-labs/aave-governance-ui-helpers/-/aave-governance-ui-helpers-3.1.5.tgz#028bd728c379d567201a97c57ade28f197ef90c1"
+ integrity sha512-OX7kbA6+V6ot/XA3ue1HFnxyhRT8v2Yllah4njXr7VH+PxeAIs1i5cbK2cN6qJ6tPHAC/JGFkGaSHIxdkjB3TQ==
dependencies:
bs58 "^5.0.0"
dayjs "^1.11.10"