|
1 |
| -import { useCallback, useEffect, useState } from "react"; |
2 | 1 | import web3DeriveAccount from "../temp/web3-derive-account";
|
3 |
| - |
4 |
| -const funcs = [ |
5 |
| - { |
6 |
| - URL: process.env.REACT_APP_USER_SETTINGS_URL, |
7 |
| - createDerived: false, |
8 |
| - method: "GET", |
9 |
| - name: "getUserSettings", |
10 |
| - payload: "settings", |
11 |
| - signingMethod: "derived", |
12 |
| - }, |
13 |
| - { |
14 |
| - URL: process.env.REACT_APP_USER_SETTINGS_URL, |
15 |
| - createDerived: true, |
16 |
| - method: "PATCH", |
17 |
| - name: "patchUserSettings", |
18 |
| - payload: "settings", |
19 |
| - signingMethod: "derived", |
20 |
| - }, |
21 |
| - { |
22 |
| - URL: process.env.REACT_APP_JUSTIFICATIONS_URL, |
23 |
| - method: "GET", |
24 |
| - name: "getJustifications", |
25 |
| - signingMethod: null, |
26 |
| - }, |
27 |
| - { |
28 |
| - URL: process.env.REACT_APP_JUSTIFICATIONS_URL, |
29 |
| - createDerived: true, |
30 |
| - method: "PUT", |
31 |
| - name: "putJustifications", |
32 |
| - payload: "justification", |
33 |
| - signingMethod: "derived", |
34 |
| - }, |
35 |
| -]; |
| 2 | +import axios from "axios"; |
36 | 3 |
|
37 | 4 | const chainIdToNetwork = {
|
38 | 5 | 1: "mainnet",
|
39 | 6 | 5: "goerli",
|
40 | 7 | 100: "xdai",
|
41 |
| - 10200: "chiado", |
42 | 8 | };
|
43 | 9 |
|
44 |
| -export const API = funcs.reduce((acc, f) => { |
45 |
| - acc[f.name] = async (web3, account, payload) => { |
46 |
| - let derivedAccount; |
47 |
| - if (f.signingMethod === "derived") |
48 |
| - derivedAccount = await web3DeriveAccount( |
49 |
| - web3, |
50 |
| - account, |
51 |
| - "To keep your data safe and to use certain features of Kleros, we ask that you sign these messages to create a secret key for your account. This key is unrelated from your main Ethereum account and will not be able to send any transactions.", |
52 |
| - f.createDerived |
53 |
| - ); |
54 |
| - |
55 |
| - const chainId = await web3.eth.getChainId(); |
56 |
| - const network = chainIdToNetwork[chainId]; |
57 |
| - if (!f.payload) { |
58 |
| - payload["network"] = network === "main" ? "mainnet" : network; |
59 |
| - } |
60 |
| - |
61 |
| - // Use different signing method depending on the situation |
62 |
| - let signature; |
63 |
| - if (f.signingMethod === "derived" && derivedAccount) { |
64 |
| - signature = derivedAccount.sign(JSON.stringify(payload)).signature; |
65 |
| - } else if (f.signingMethod === "personal") { |
66 |
| - signature = await web3.eth.sign(JSON.stringify(payload), account); |
67 |
| - } |
68 |
| - |
69 |
| - const func = () => |
70 |
| - fetch(f.URL, { |
71 |
| - body: JSON.stringify({ |
72 |
| - payload: f.payload |
73 |
| - ? { |
74 |
| - address: account, |
75 |
| - network: network === "main" ? "mainnet" : network, |
76 |
| - signature, |
77 |
| - [f.payload]: payload, |
78 |
| - } |
79 |
| - : payload, |
80 |
| - }), |
81 |
| - headers: { "Content-Type": "application/json" }, |
82 |
| - method: f.method === "GET" ? "POST" : f.method, |
83 |
| - }).then((res) => res.json()); |
84 |
| - const res = await func(); |
85 |
| - if (res.error && derivedAccount) { |
86 |
| - const settings = { |
87 |
| - derivedAccountAddress: { |
88 |
| - S: derivedAccount.address, |
89 |
| - }, |
90 |
| - }; |
91 |
| - await fetch(process.env.REACT_APP_USER_SETTINGS_URL, { |
92 |
| - body: JSON.stringify({ |
93 |
| - payload: { |
94 |
| - address: account, |
95 |
| - settings, |
96 |
| - signature: await web3.eth.personal.sign(JSON.stringify(settings), account), |
97 |
| - }, |
98 |
| - }), |
99 |
| - headers: { "Content-Type": "application/json" }, |
100 |
| - method: "PATCH", |
101 |
| - }).then((res) => res.json()); |
102 |
| - return func(); |
103 |
| - } |
104 |
| - return res; |
105 |
| - }; |
106 |
| - |
107 |
| - Object.defineProperty(acc[f.name], "name", { value: f.name }); |
108 |
| - |
109 |
| - return acc; |
110 |
| -}, {}); |
111 |
| - |
112 |
| -export const useAPI = funcs.reduce((acc, f) => { |
113 |
| - acc[f.name] = function useHook(web3, account, payload) { |
114 |
| - const [state, setState] = useState(f.method === "GET" ? "pending" : undefined); |
115 |
| - let mounted = true; |
116 |
| - |
117 |
| - const send = useCallback( |
118 |
| - async (payload) => { |
119 |
| - let state; |
120 |
| - try { |
121 |
| - if (state !== "pending") setState("pending"); |
122 |
| - state = await API[f.name](web3, account, payload); |
123 |
| - } catch (err) { |
124 |
| - console.error(err); |
125 |
| - state = { error: "An unexpected error occurred." }; |
126 |
| - } |
127 |
| - |
128 |
| - if (mounted) { |
129 |
| - setState(state); |
130 |
| - } |
| 10 | +export const API = async ({ url, method, createDerived, web3, account, payload }) => { |
| 11 | + let derivedAccount; |
| 12 | + derivedAccount = await web3DeriveAccount( |
| 13 | + web3, |
| 14 | + account, |
| 15 | + "To keep your data safe and to use certain features of Kleros, we ask that you sign these messages to create a secret key for your account. This key is unrelated from your main Ethereum account and will not be able to send any transactions.", |
| 16 | + createDerived |
| 17 | + ); |
| 18 | + |
| 19 | + const network = chainIdToNetwork[await web3.eth.getChainId()]; |
| 20 | + if (!payload) payload["network"] = network === "main" ? "mainnet" : network; |
| 21 | + |
| 22 | + const signature = derivedAccount |
| 23 | + ? derivedAccount.sign(JSON.stringify(payload)).signature |
| 24 | + : await web3.eth.sign(JSON.stringify(payload), account); |
| 25 | + |
| 26 | + const func = () => |
| 27 | + axios[method.toLocaleLowerCase()](url, { |
| 28 | + payload: { |
| 29 | + address: account, |
| 30 | + network: network === "main" ? "mainnet" : network, |
| 31 | + signature, |
| 32 | + ...payload, |
131 | 33 | },
|
132 |
| - // eslint-disable-next-line react-hooks/exhaustive-deps |
133 |
| - [web3, account] |
134 |
| - ); |
135 |
| - |
136 |
| - useEffect(() => { |
137 |
| - if (f.method === "GET") { |
138 |
| - send(payload); |
139 |
| - return () => { |
140 |
| - // eslint-disable-next-line react-hooks/exhaustive-deps |
141 |
| - mounted = false; |
142 |
| - }; |
143 |
| - } |
144 |
| - }, [web3, account, JSON.stringify(payload)]); |
| 34 | + }); |
145 | 35 |
|
146 |
| - return f.method === "GET" ? state : { send, state }; |
147 |
| - }; |
| 36 | + const res = func(); |
148 | 37 |
|
149 |
| - Object.defineProperty(acc[f.name], "name", { value: `use${ucFirst(f.name)}` }); |
150 |
| - |
151 |
| - return acc; |
152 |
| -}, {}); |
| 38 | + if (!res.ok && derivedAccount) { |
| 39 | + const settings = { derivedAccountAddress: { S: derivedAccount.address } }; |
| 40 | + await axios.patch(process.env.REACT_APP_USER_SETTINGS_URL, { |
| 41 | + payload: { |
| 42 | + address: account, |
| 43 | + settings, |
| 44 | + signature: await web3.eth.personal.sign(JSON.stringify(settings), account), |
| 45 | + }, |
| 46 | + }); |
153 | 47 |
|
154 |
| -function ucFirst(str) { |
155 |
| - if (str.length === 0) { |
156 |
| - return ""; |
| 48 | + return func(); |
157 | 49 | }
|
158 | 50 |
|
159 |
| - return str.charAt(0).toUpperCase() + str.substring(1); |
160 |
| -} |
| 51 | + return res; |
| 52 | +}; |
0 commit comments