refactor: abstracts common rpc handling into createJsonRpcRequestHandler

This commit is contained in:
Ben Kremer 2022-02-04 15:08:29 +01:00
parent 55fff706cf
commit 575f21e814

View File

@ -53,6 +53,13 @@ import {
SToggleContainer, SToggleContainer,
} from "./components/app"; } from "./components/app";
interface FormattedRpcResponse {
method: string;
address: string;
valid: boolean;
result: string;
}
export default function App() { export default function App() {
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [pending, setPending] = useState(false); const [pending, setPending] = useState(false);
@ -317,204 +324,174 @@ export default function App() {
setChainData(chainData); setChainData(chainData);
}; };
const testSendTransaction = async (chainId: string) => { // ----- EVM RPC -----
if (typeof client === "undefined") {
throw new Error("WalletConnect is not initialized");
}
if (typeof session === "undefined") {
throw new Error("Session is not connected");
}
try { const createJsonRpcRequestHandler =
setPending(true); (rpcRequest: (...requestArgs: [any]) => Promise<FormattedRpcResponse>) =>
// get ethereum address async (chainId: string) => {
const account = accounts.find(account => account.startsWith(chainId)); if (typeof client === "undefined") {
if (account === undefined) throw new Error("Account is not found"); throw new Error("WalletConnect is not initialized");
const address = account.split(":").pop(); }
if (address === undefined) throw new Error("Address is invalid"); if (typeof session === "undefined") {
throw new Error("Session is not connected");
// open modal
openRequestModal();
const tx = await formatTestTransaction(account);
const balance = BigNumber.from(balances[account][0].balance || "0");
if (balance.lt(BigNumber.from(tx.gasPrice).mul(tx.gasLimit))) {
const formattedResult = {
method: "eth_sendTransaction",
address,
valid: false,
result: "Insufficient funds for intrinsic transaction cost",
};
setResult(formattedResult);
return;
} }
const result = await client.request({ try {
topic: session.topic, setPending(true);
chainId, const result = await rpcRequest(chainId);
request: { setResult(result);
method: "eth_sendTransaction", } catch (err) {
params: [tx], console.error(err);
}, setResult(null);
}); } finally {
setPending(false);
}
};
// format displayed result const testSendTransaction = createJsonRpcRequestHandler(async (chainId: string) => {
const formattedResult = { // get ethereum address
const account = accounts.find(account => account.startsWith(chainId));
if (account === undefined) throw new Error("Account is not found");
const address = account.split(":").pop();
if (address === undefined) throw new Error("Address is invalid");
// open modal
openRequestModal();
const tx = await formatTestTransaction(account);
const balance = BigNumber.from(balances[account][0].balance || "0");
if (balance.lt(BigNumber.from(tx.gasPrice).mul(tx.gasLimit))) {
return {
method: "eth_sendTransaction", method: "eth_sendTransaction",
address, address,
valid: true, valid: false,
result, result: "Insufficient funds for intrinsic transaction cost",
}; };
// display result
setResult(formattedResult);
} catch (e) {
console.error(e);
setResult(null);
} finally {
setPending(false);
}
};
const testSignPersonalMessage = async (chainId: string) => {
if (typeof client === "undefined") {
throw new Error("WalletConnect is not initialized");
}
if (typeof session === "undefined") {
throw new Error("Session is not connected");
} }
try { const result: string = await client!.request({
setPending(true); topic: session!.topic,
// test message chainId,
const message = `My email is john@doe.com - ${Date.now()}`; request: {
method: "eth_sendTransaction",
params: [tx],
},
});
// encode message (hex) // format displayed result
const hexMsg = encoding.utf8ToHex(message, true); return {
method: "eth_sendTransaction",
address,
valid: true,
result,
};
});
// get ethereum address const testSignPersonalMessage = createJsonRpcRequestHandler(async (chainId: string) => {
const account = accounts.find(account => account.startsWith(chainId)); // test message
if (account === undefined) throw new Error("Account is not found"); const message = `My email is john@doe.com - ${Date.now()}`;
const address = account.split(":").pop();
if (address === undefined) throw new Error("Address is invalid");
// personal_sign params // encode message (hex)
const params = [hexMsg, address]; const hexMsg = encoding.utf8ToHex(message, true);
// open modal // get ethereum address
openRequestModal(); const account = accounts.find(account => account.startsWith(chainId));
if (account === undefined) throw new Error("Account is not found");
const address = account.split(":").pop();
if (address === undefined) throw new Error("Address is invalid");
// send message // personal_sign params
const result = await client.request({ const params = [hexMsg, address];
topic: session.topic,
chainId,
request: {
method: "personal_sign",
params,
},
});
// split chainId // open modal
const [namespace, reference] = chainId.split(":"); openRequestModal();
const targetChainData = chainData[namespace][reference]; // send message
const result: string = await client!.request({
if (typeof targetChainData === "undefined") { topic: session!.topic,
throw new Error(`Missing chain data for chainId: ${chainId}`); chainId,
} request: {
const rpcUrl = targetChainData.rpc[0];
// verify signature
const hash = hashPersonalMessage(message);
const valid = await verifySignature(address, result, hash, rpcUrl);
// format displayed result
const formattedResult = {
method: "personal_sign", method: "personal_sign",
address, params,
valid, },
result, });
};
// display result // split chainId
setResult(formattedResult); const [namespace, reference] = chainId.split(":");
} catch (e) {
console.error(e); const targetChainData = chainData[namespace][reference];
setResult(null);
} finally { if (typeof targetChainData === "undefined") {
setPending(false); throw new Error(`Missing chain data for chainId: ${chainId}`);
} }
};
const testSignTypedData = async (chainId: string) => { const rpcUrl = targetChainData.rpc[0];
if (typeof client === "undefined") {
throw new Error("WalletConnect is not initialized");
}
if (typeof session === "undefined") {
throw new Error("Session is not connected");
}
try {
setPending(true);
// test message // verify signature
const message = JSON.stringify(eip712.example); const hash = hashPersonalMessage(message);
const valid = await verifySignature(address, result, hash, rpcUrl);
// get ethereum address // format displayed result
const account = accounts.find(account => account.startsWith(chainId)); return {
if (account === undefined) throw new Error("Account is not found"); method: "personal_sign",
const address = account.split(":").pop(); address,
if (address === undefined) throw new Error("Address is invalid"); valid,
result,
};
});
// eth_signTypedData params const testSignTypedData = createJsonRpcRequestHandler(async (chainId: string) => {
const params = [address, message]; // test message
const message = JSON.stringify(eip712.example);
// open modal // get ethereum address
openRequestModal(); const account = accounts.find(account => account.startsWith(chainId));
if (account === undefined) throw new Error("Account is not found");
const address = account.split(":").pop();
if (address === undefined) throw new Error("Address is invalid");
// send message // eth_signTypedData params
const result = await client.request({ const params = [address, message];
topic: session.topic,
chainId,
request: {
method: "eth_signTypedData",
params,
},
});
// split chainId // open modal
const [namespace, reference] = chainId.split(":"); openRequestModal();
const targetChainData = chainData[namespace][reference]; // send message
const result = await client!.request({
if (typeof targetChainData === "undefined") { topic: session!.topic,
throw new Error(`Missing chain data for chainId: ${chainId}`); chainId,
} request: {
const rpcUrl = targetChainData.rpc[0];
// verify signature
const hash = hashTypedDataMessage(message);
const valid = await verifySignature(address, result, hash, rpcUrl);
// format displayed result
const formattedResult = {
method: "eth_signTypedData", method: "eth_signTypedData",
address, params,
valid, },
result, });
};
// display result // split chainId
setResult(formattedResult); const [namespace, reference] = chainId.split(":");
} catch (e) {
console.error(e); const targetChainData = chainData[namespace][reference];
setResult(null);
} finally { if (typeof targetChainData === "undefined") {
setPending(false); throw new Error(`Missing chain data for chainId: ${chainId}`);
} }
};
const rpcUrl = targetChainData.rpc[0];
// verify signature
const hash = hashTypedDataMessage(message);
const valid = await verifySignature(address, result, hash, rpcUrl);
// format displayed result
return {
method: "eth_signTypedData",
address,
valid,
result,
};
});
// ------ COSMOS RPC ------
const testSignDirect = async (chainId: string) => { const testSignDirect = async (chainId: string) => {
if (typeof client === "undefined") { if (typeof client === "undefined") {