Skip to content

Commit a874340

Browse files
authored
fix: make manager safe app compatible (#3737)
* fix: make manager safe app compatible * adds missing dependency to tests * add missing deps for tests
1 parent fc33919 commit a874340

31 files changed

+303
-105
lines changed

packages/round-manager/package.json

+2
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
"@openzeppelin/merkle-tree": "^1.0.2",
3939
"@rainbow-me/rainbowkit": "2.1.2",
4040
"@reduxjs/toolkit": "^1.8.1",
41+
"@safe-global/safe-apps-provider": "^0.18.5",
42+
"@safe-global/safe-apps-react-sdk": "^4.7.2",
4143
"@sentry/integrations": "^7.28.0",
4244
"@sentry/react": "^7.27.0",
4345
"@sentry/tracing": "^7.26.0",
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
{
2+
"short_name": "Manager",
3+
"name": "Gitcoin Safe App Manager",
4+
"description": "Gitcoin Safe App Manager",
5+
"icons": [
6+
{
7+
"src": "manager-logo.svg",
8+
"sizes": "any",
9+
"type": "image/svg+xml"
10+
},
11+
{
12+
"src": "favicon.ico",
13+
"sizes": "64x64 32x32 24x24 16x16",
14+
"type": "image/x-icon"
15+
},
16+
{
17+
"src": "favicon.ico",
18+
"sizes": "64x64 32x32 24x24 16x16",
19+
"type": "image/x-icon"
20+
},
21+
{
22+
"src": "logo192.png",
23+
"type": "image/png",
24+
"sizes": "192x192"
25+
},
26+
{
27+
"src": "logo512.png",
28+
"type": "image/png",
29+
"sizes": "512x512"
30+
}
31+
],
32+
"start_url": ".",
33+
"display": "standalone",
34+
"theme_color": "#FFFFFF",
35+
"background_color": "#FFFFFF"
36+
}

packages/round-manager/setUpProxy.js

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// App is an express application, we can add an express middleware that will set headers for manifest.json request
2+
// https://create-react-app.dev/docs/proxying-api-requests-in-development/#configuring-the-proxy-manually
3+
4+
module.exports = function (app) {
5+
app.use("/manifest.json", function (req, res, next) {
6+
res.set({
7+
"Access-Control-Allow-Origin": "*",
8+
"Access-Control-Allow-Methods": "GET",
9+
"Access-Control-Allow-Headers":
10+
"X-Requested-With, content-type, Authorization",
11+
});
12+
next();
13+
});
14+
};

packages/round-manager/src/app/wagmi.ts

+43-11
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,58 @@
11
import "@rainbow-me/rainbowkit/styles.css";
22
import { QueryClient } from "@tanstack/react-query";
3-
import { Chain as RChain, getDefaultConfig } from "@rainbow-me/rainbowkit";
43
import { allNetworks, mainnetNetworks } from "common/src/chains";
54
import { getClient, getConnectorClient } from "@wagmi/core";
65
import { providers } from "ethers";
7-
import { type Account, type Chain, type Client, type Transport } from "viem";
6+
import {
7+
http,
8+
type Account,
9+
type Chain,
10+
type Client,
11+
type Transport,
12+
} from "viem";
813
import { Connector } from "wagmi";
9-
10-
export const allChains: RChain[] =
11-
process.env.REACT_APP_ENV === "development" ? allNetworks : mainnetNetworks;
14+
import {
15+
rainbowWallet,
16+
safeWallet,
17+
walletConnectWallet,
18+
coinbaseWallet,
19+
} from "@rainbow-me/rainbowkit/wallets";
20+
import { connectorsForWallets } from "@rainbow-me/rainbowkit";
1221

1322
/* TODO: remove hardcoded value once we have environment variables validation */
1423
const projectId =
1524
process.env.REACT_APP_WALLETCONNECT_PROJECT_ID ??
1625
"2685061cae0bcaf2b244446153eda9e1";
26+
const connectors = connectorsForWallets(
27+
[
28+
{
29+
groupName: "Popular",
30+
wallets: [safeWallet, rainbowWallet, walletConnectWallet, coinbaseWallet],
31+
},
32+
],
33+
{
34+
appName: "Gitcoin Manager",
35+
projectId,
36+
}
37+
);
38+
export const allChains: Chain[] =
39+
process.env.REACT_APP_ENV === "development" ? allNetworks : mainnetNetworks;
40+
41+
import { createConfig } from "wagmi";
42+
43+
const transports = allChains.reduce(
44+
(acc, chain) => {
45+
acc[chain.id] = http();
46+
return acc;
47+
},
48+
{} as Record<number, ReturnType<typeof http>>
49+
);
1750

18-
export const config = getDefaultConfig({
19-
appName: "Gitcoin Manager",
20-
projectId,
21-
chains: [...allChains] as [Chain, ...Chain[]],
22-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
23-
}) as any;
51+
export const config = createConfig({
52+
chains: [...allChains] as unknown as readonly [Chain, ...Chain[]],
53+
connectors,
54+
transports,
55+
});
2456

2557
const queryClient = new QueryClient();
2658

packages/round-manager/src/context/program/__tests__/ReadProgramContext.test.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,11 @@ jest.mock("wagmi", () => ({
2626
chainId: 1,
2727
address: "0x0",
2828
}),
29+
createConfig: jest.fn(),
2930
}));
3031
jest.mock("@rainbow-me/rainbowkit", () => ({
3132
ConnectButton: jest.fn(),
32-
getDefaultConfig: jest.fn(),
33+
connectorsForWallets: jest.fn(),
3334
}));
3435
jest.mock("data-layer", () => ({
3536
...jest.requireActual("data-layer"),

packages/round-manager/src/context/round/__tests__/ReclaimFundsContext.test.tsx

+1-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ jest.mock("wagmi", () => ({
1212
useAccount: () => ({
1313
chainId: 1,
1414
}),
15+
createConfig: jest.fn(),
1516
}));
1617
jest.mock("../../../features/api/payoutStrategy/payoutStrategy");
1718

@@ -23,7 +24,6 @@ jest.mock("viem", () => ({
2324
jest.mock("common", () => ({
2425
...jest.requireActual("common"),
2526
useAllo: jest.fn(),
26-
2727
}));
2828

2929
const alloBackend = new AlloV1({
@@ -37,7 +37,6 @@ const alloBackend = new AlloV1({
3737
transactionSender: createMockTransactionSender(),
3838
});
3939

40-
4140
const testParams: ReclaimFundsParams = {
4241
allo: alloBackend,
4342
payoutStrategy: "0x0000000000000000000000000000000000000001",

packages/round-manager/src/context/round/__tests__/RoundContext.test.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@ jest.mock("wagmi", () => ({
1212
useAccount: () => ({
1313
chainId: 1,
1414
}),
15+
createConfig: jest.fn(),
1516
}));
1617
jest.mock("@rainbow-me/rainbowkit", () => ({
1718
ConnectButton: jest.fn(),
18-
getDefaultConfig: jest.fn(),
19+
connectorsForWallets: jest.fn(),
1920
}));
2021
jest.mock("../../../features/common/Auth", () => ({
2122
useWallet: () => mockWallet,

packages/round-manager/src/context/round/__tests__/UpdateRoundContext.test.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,11 @@ jest.mock("wagmi", () => ({
3131
useAccount: () => ({
3232
chainId: 1,
3333
}),
34+
createConfig: jest.fn(),
3435
}));
3536
jest.mock("@rainbow-me/rainbowkit", () => ({
3637
ConnectButton: jest.fn(),
37-
getDefaultConfig: jest.fn(),
38+
connectorsForWallets: jest.fn(),
3839
}));
3940

4041
jest.mock("../../../features/api/round");
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { useEffect } from "react";
2+
3+
import { useConnect, useAccount } from "wagmi";
4+
5+
const AUTOCONNECTED_CONNECTOR_IDS = ["safe"];
6+
7+
function useAutoConnect() {
8+
const { connect, connectors } = useConnect();
9+
const { address } = useAccount();
10+
11+
useEffect(() => {
12+
AUTOCONNECTED_CONNECTOR_IDS.forEach((connector) => {
13+
const connectorInstance = connectors.find((c) => c.id === connector);
14+
const isIframe = window.top !== window.self;
15+
if (connectorInstance && isIframe) {
16+
connect({ connector: connectorInstance });
17+
}
18+
});
19+
}, [connect, connectors, address]);
20+
}
21+
22+
export const SafeAutoConnect = ({
23+
children,
24+
}: {
25+
children: JSX.Element | JSX.Element[];
26+
}) => {
27+
useAutoConnect();
28+
return <>{children}</>;
29+
};

packages/round-manager/src/features/api/__tests__/round.test.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,11 @@ jest.mock("wagmi", () => ({
2020
useAccount: () => ({
2121
chainId: 1,
2222
}),
23+
createConfig: jest.fn(),
2324
}));
2425
jest.mock("@rainbow-me/rainbowkit", () => ({
2526
ConnectButton: jest.fn(),
26-
getDefaultConfig: jest.fn(),
27+
connectorsForWallets: jest.fn(),
2728
}));
2829

2930
describe("TransactionBuilder", () => {

packages/round-manager/src/features/common/__tests__/ErrorModal.test.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import ErrorModal from "../../common/ErrorModal";
55
jest.mock("../../common/Auth");
66
jest.mock("@rainbow-me/rainbowkit", () => ({
77
ConnectButton: jest.fn(),
8-
getDefaultConfig: jest.fn(),
8+
connectorsForWallets: jest.fn(),
99
}));
1010

1111
describe("<ErrorModal />", () => {

packages/round-manager/src/features/program/__tests__/CreateProgramPage.test.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jest.mock("../../api/ipfs");
1818
jest.mock("../../common/Auth");
1919
jest.mock("@rainbow-me/rainbowkit", () => ({
2020
ConnectButton: jest.fn(),
21-
getDefaultConfig: jest.fn(),
21+
connectorsForWallets: jest.fn(),
2222
}));
2323

2424
jest.mock("../../../constants", () => ({

packages/round-manager/src/features/program/__tests__/ListProgramPage.test.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,11 @@ jest.mock("wagmi", () => ({
1414
useAccount: () => ({
1515
chainId: 1,
1616
}),
17+
createConfig: jest.fn(),
1718
}));
1819
jest.mock("@rainbow-me/rainbowkit", () => ({
1920
ConnectButton: jest.fn(),
20-
getDefaultConfig: jest.fn(),
21+
connectorsForWallets: jest.fn(),
2122
}));
2223
jest.mock("data-layer", () => ({
2324
...jest.requireActual("data-layer"),

packages/round-manager/src/features/program/__tests__/ViewProgramPage.test.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ jest.mock("../../common/Auth");
2323
jest.mock("../../api/program");
2424
jest.mock("@rainbow-me/rainbowkit", () => ({
2525
ConnectButton: jest.fn(),
26-
getDefaultConfig: jest.fn(),
26+
connectorsForWallets: jest.fn(),
2727
}));
2828
jest.mock("react-router-dom", () => ({
2929
...jest.requireActual("react-router-dom"),

packages/round-manager/src/features/round/ViewApplicationPage.tsx

+7-4
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,7 @@ export default function ViewApplicationPage() {
170170
};
171171

172172
if (roundChainId) fetchApplications();
173-
}, [roundChainId, roundId]);
173+
}, [roundChainId, roundId, id, dataLayer]);
174174

175175
useEffect(() => {
176176
if (contractUpdatingStatus === ProgressStatus.IS_ERROR) {
@@ -334,7 +334,10 @@ export default function ViewApplicationPage() {
334334

335335
if (application?.answers && application.answers.length > 0) {
336336
for (let _answerBlock of application.answers) {
337-
if (_answerBlock.encryptedAnswer && !isLitUnavailable(round.chainId!)) {
337+
if (
338+
_answerBlock.encryptedAnswer &&
339+
!isLitUnavailable(round.chainId!)
340+
) {
338341
try {
339342
const encryptedAnswer = _answerBlock.encryptedAnswer;
340343
const base64EncryptedString = [
@@ -349,7 +352,7 @@ export default function ViewApplicationPage() {
349352
chainId: Number(roundChainId!),
350353
contract: roundId.startsWith("0x")
351354
? roundId
352-
: round?.payoutStrategy.id ?? "",
355+
: (round?.payoutStrategy.id ?? ""),
353356
});
354357

355358
const decryptedString = await lit.decryptString(
@@ -816,7 +819,7 @@ export default function ViewApplicationPage() {
816819
answerBlocks?.map((block: AnswerBlock) => {
817820
const answerText = Array.isArray(block.answer)
818821
? block.answer.join(", ")
819-
: block.answer ?? "";
822+
: (block.answer ?? "");
820823

821824
return (
822825
<div key={block.questionId} className="pb-5">

packages/round-manager/src/features/round/__tests__/ApplicationsToApproveReject.test.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,11 @@ jest.mock("wagmi", () => ({
2929
useAccount: () => ({
3030
chainId: 1,
3131
}),
32+
createConfig: jest.fn(),
3233
}));
3334
jest.mock("@rainbow-me/rainbowkit", () => ({
3435
ConnectButton: jest.fn(),
35-
getDefaultConfig: jest.fn(),
36+
connectorsForWallets: jest.fn(),
3637
}));
3738
jest.mock("../../api/application");
3839
jest.mock("../../common/Auth", () => ({

packages/round-manager/src/features/round/__tests__/ApplicationsToReview.test.tsx

+2-1
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,12 @@ jest.mock("wagmi", () => ({
3030
useAccount: () => ({
3131
chainId: 1,
3232
}),
33+
createConfig: jest.fn(),
3334
}));
3435

3536
jest.mock("@rainbow-me/rainbowkit", () => ({
3637
ConnectButton: jest.fn(),
37-
getDefaultConfig: jest.fn(),
38+
connectorsForWallets: jest.fn(),
3839
}));
3940

4041
jest.mock("common/src/allo/backends/allo-v1");

packages/round-manager/src/features/round/__tests__/CreateRoundPage.test.tsx

+3-4
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@ jest.mock("wagmi", () => ({
1212
useAccount: () => ({
1313
chainId: 1,
1414
}),
15+
createConfig: jest.fn(),
1516
}));
1617
jest.mock("@rainbow-me/rainbowkit", () => ({
1718
ConnectButton: jest.fn(),
18-
getDefaultConfig: jest.fn(),
19+
connectorsForWallets: jest.fn(),
1920
}));
2021
jest.mock("../../common/Navbar");
2122
jest.mock("../../common/Auth");
@@ -33,9 +34,7 @@ jest.mock("react-router-dom", () => ({
3334
}));
3435

3536
describe("<CreateRoundPage />", () => {
36-
beforeEach(() => {
37-
38-
});
37+
beforeEach(() => {});
3938

4039
it("sends program to form wizard", () => {
4140
const programs = [makeProgramData({ id: programId })];

0 commit comments

Comments
 (0)