Skip to content

Commit 3d217da

Browse files
committed
feat(web): atlas-upload-to-ipfs-integration
1 parent 39cf66d commit 3d217da

File tree

7 files changed

+137
-172
lines changed

7 files changed

+137
-172
lines changed

web/netlify/functions/uploadToIPFS.ts

-101
This file was deleted.

web/netlify/middleware/authMiddleware.ts

-37
This file was deleted.

web/src/context/AtlasProvider.tsx

+35-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
addUser as addUserToAtlas,
1414
fetchUser,
1515
updateUser as updateUserInAtlas,
16+
uploadToIpfs,
1617
type User,
1718
type AddUserData,
1819
type UpdateUserData,
@@ -26,11 +27,13 @@ interface IAtlasProvider {
2627
isAddingUser: boolean;
2728
isFetchingUser: boolean;
2829
isUpdatingUser: boolean;
30+
isUploadingFile: boolean;
2931
user: User | undefined;
3032
userExists: boolean;
3133
authoriseUser: () => void;
3234
addUser: (userSettings: AddUserData) => Promise<boolean>;
3335
updateUser: (userSettings: UpdateUserData) => Promise<boolean>;
36+
uploadFile: (file: File) => Promise<string | null>;
3437
}
3538

3639
const Context = createContext<IAtlasProvider | undefined>(undefined);
@@ -49,6 +52,7 @@ const AtlasProvider: React.FC<{ children?: React.ReactNode }> = ({ children }) =
4952
const [isAddingUser, setIsAddingUser] = useState(false);
5053
const [isUpdatingUser, setIsUpdatingUser] = useState(false);
5154
const [isVerified, setIsVerified] = useState(false);
55+
const [isUploadingFile, setIsUploadingFile] = useState(false);
5256
const { signMessageAsync } = useSignMessage();
5357

5458
const atlasGqlClient = useMemo(() => {
@@ -123,7 +127,7 @@ const AtlasProvider: React.FC<{ children?: React.ReactNode }> = ({ children }) =
123127
// this would change based on the fields we have and what defines a user to be existing
124128
const userExists = useMemo(() => {
125129
if (!user) return false;
126-
return user.email ? true : false;
130+
return !isUndefined(user.email);
127131
}, [user]);
128132

129133
/**
@@ -200,6 +204,32 @@ const AtlasProvider: React.FC<{ children?: React.ReactNode }> = ({ children }) =
200204
[address, isVerified, setIsUpdatingUser, atlasGqlClient, refetchUser]
201205
);
202206

207+
/**
208+
* @description upload file to ipfs
209+
* @param {File} file - file to be uploaded
210+
* @returns {Promise<string | null>} A promise that resolves to the ipfs cid if file was uploaded successfully else
211+
* null
212+
*/
213+
const uploadFile = useCallback(
214+
async (file: File) => {
215+
try {
216+
if (!address || !isVerified) return null;
217+
setIsUploadingFile(true);
218+
219+
const hash = await uploadToIpfs(atlasGqlClient, file);
220+
221+
return hash ? `/ipfs/${hash}` : null;
222+
} catch (err: any) {
223+
// eslint-disable-next-line
224+
console.log("Upload File Error : ", err?.message);
225+
return null;
226+
} finally {
227+
setIsUploadingFile(false);
228+
}
229+
},
230+
[address, isVerified, setIsUploadingFile, atlasGqlClient]
231+
);
232+
203233
return (
204234
<Context.Provider
205235
value={useMemo(
@@ -214,6 +244,8 @@ const AtlasProvider: React.FC<{ children?: React.ReactNode }> = ({ children }) =
214244
updateUser,
215245
isUpdatingUser,
216246
userExists,
247+
isUploadingFile,
248+
uploadFile,
217249
}),
218250
[
219251
isVerified,
@@ -226,6 +258,8 @@ const AtlasProvider: React.FC<{ children?: React.ReactNode }> = ({ children }) =
226258
updateUser,
227259
isUpdatingUser,
228260
userExists,
261+
isUploadingFile,
262+
uploadFile,
229263
]
230264
)}
231265
>

web/src/pages/Cases/CaseDetails/Evidence/SubmitEvidenceModal.tsx

+25-24
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ import { useWalletClient, usePublicClient, useConfig } from "wagmi";
77

88
import { Textarea, Button, FileUploader } from "@kleros/ui-components-library";
99

10+
import { useAtlasProvider } from "context/AtlasProvider";
1011
import { simulateEvidenceModuleSubmitEvidence } from "hooks/contracts/generated";
11-
import { uploadFormDataToIPFS } from "utils/uploadFormDataToIPFS";
1212
import { wrapWithToast, OPTIONS as toastOptions } from "utils/wrapWithToast";
1313

1414
import EnsureAuth from "components/EnsureAuth";
@@ -61,23 +61,28 @@ const SubmitEvidenceModal: React.FC<{
6161
const [isSending, setIsSending] = useState(false);
6262
const [message, setMessage] = useState("");
6363
const [file, setFile] = useState<File>();
64+
const { uploadFile } = useAtlasProvider();
6465

6566
const submitEvidence = useCallback(async () => {
66-
setIsSending(true);
67-
const evidenceJSON = await constructEvidence(message, file);
68-
69-
const { request } = await simulateEvidenceModuleSubmitEvidence(wagmiConfig, {
70-
args: [BigInt(evidenceGroup), JSON.stringify(evidenceJSON)],
71-
});
72-
73-
if (!walletClient) return;
74-
await wrapWithToast(async () => await walletClient.writeContract(request), publicClient)
75-
.then(() => {
76-
setMessage("");
77-
close();
78-
})
79-
.finally(() => setIsSending(false));
80-
}, [publicClient, wagmiConfig, walletClient, close, evidenceGroup, file, message, setIsSending]);
67+
try {
68+
setIsSending(true);
69+
const evidenceJSON = await constructEvidence(uploadFile, message, file);
70+
71+
const { request } = await simulateEvidenceModuleSubmitEvidence(wagmiConfig, {
72+
args: [BigInt(evidenceGroup), JSON.stringify(evidenceJSON)],
73+
});
74+
75+
if (!walletClient || !publicClient) return;
76+
await wrapWithToast(async () => await walletClient.writeContract(request), publicClient)
77+
.then(() => {
78+
setMessage("");
79+
close();
80+
})
81+
.finally(() => setIsSending(false));
82+
} catch {
83+
setIsSending(false);
84+
}
85+
}, [publicClient, wagmiConfig, walletClient, close, evidenceGroup, file, message, setIsSending, uploadFile]);
8186

8287
return (
8388
<StyledModal {...{ isOpen }}>
@@ -96,16 +101,12 @@ const SubmitEvidenceModal: React.FC<{
96101
);
97102
};
98103

99-
const constructEvidence = async (msg: string, file?: File) => {
100-
let fileURI: string | undefined = undefined;
104+
const constructEvidence = async (uploadFile: (file: File) => Promise<string | null>, msg: string, file?: File) => {
105+
let fileURI: string | null = null;
101106
if (file) {
102107
toast.info("Uploading to IPFS", toastOptions);
103-
const fileFormData = new FormData();
104-
fileFormData.append("data", file, file.name);
105-
fileURI = await uploadFormDataToIPFS(fileFormData).then(async (res) => {
106-
const response = await res.json();
107-
return response["cids"][0];
108-
});
108+
fileURI = await uploadFile(file);
109+
if (!fileURI) throw new Error("Error uploading evidence file");
109110
}
110111
return { name: "Evidence", description: msg, fileURI };
111112
};

web/src/pages/Resolver/Policy/index.tsx

+6-9
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ import { toast } from "react-toastify";
55

66
import { FileUploader } from "@kleros/ui-components-library";
77

8+
import { useAtlasProvider } from "context/AtlasProvider";
89
import { useNewDisputeContext } from "context/NewDisputeContext";
9-
import { uploadFormDataToIPFS } from "utils/uploadFormDataToIPFS";
1010
import { OPTIONS as toastOptions } from "utils/wrapWithToast";
1111

1212
import { landscapeStyle } from "styles/landscapeStyle";
@@ -51,19 +51,16 @@ const StyledFileUploader = styled(FileUploader)`
5151

5252
const Policy: React.FC = () => {
5353
const { disputeData, setDisputeData, setIsPolicyUploading } = useNewDisputeContext();
54+
const { uploadFile } = useAtlasProvider();
5455

5556
const handleFileUpload = (file: File) => {
5657
setIsPolicyUploading(true);
5758
toast.info("Uploading Policy to IPFS", toastOptions);
5859

59-
const fileFormData = new FormData();
60-
fileFormData.append("data", file, file.name);
61-
62-
uploadFormDataToIPFS(fileFormData, "policy")
63-
.then(async (res) => {
64-
const response = await res.json();
65-
const policyURI = response["cids"][0];
66-
setDisputeData({ ...disputeData, policyURI });
60+
uploadFile(file)
61+
.then(async (cid) => {
62+
if (!cid) return;
63+
setDisputeData({ ...disputeData, policyURI: cid });
6764
})
6865
.catch((err) => console.log(err))
6966
.finally(() => setIsPolicyUploading(false));

web/src/utils/atlas/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ export * from "./createMessage";
44
export * from "./addUser";
55
export * from "./fetchUser";
66
export * from "./updateUser";
7+
export * from "./uploadToIpfs";

0 commit comments

Comments
 (0)