Skip to content

Commit

Permalink
6492 verify message (#1382)
Browse files Browse the repository at this point in the history
* Use viem to verify 6492 signed messages

* Keep track of the switch chain state to make the verify message functionality more robust

* Fix whitespace

* Set chain id based on current provider state

* Fix npe when using extension
  • Loading branch information
hieronymus777 authored Sep 5, 2024
1 parent f60e33a commit c8040d5
Show file tree
Hide file tree
Showing 6 changed files with 2,152 additions and 1,624 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
"next": "^13.5.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hook-form": "^7.45.2"
"react-hook-form": "^7.45.2",
"viem": "2.21.1"
},
"devDependencies": {
"@types/react": "18.2.15",
Expand Down
11 changes: 9 additions & 2 deletions src/components/RpcMethods/RpcMethodCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ import { useForm } from 'react-hook-form';
import { useCBWSDK } from '../../context/CBWSDKReactContextProvider';
import { verifySignMsg } from './method/signMessageMethods';
import { ADDR_TO_FILL } from './shortcut/const';
import { Chain, hexToNumber } from 'viem';
import { mainnet } from 'viem/chains';
import { multiChainShortcutsMap } from './shortcut/multipleChainShortcuts';

type ResponseType = string;

Expand All @@ -40,17 +43,21 @@ export function RpcMethodCard({ format, method, params, shortcuts }) {
} = useForm();

const verify = useCallback(async (response: ResponseType, data: Record<string, string>) => {
const verifyResult = verifySignMsg({
const chainId = await provider.request({ method: "eth_chainId"});
let chain = multiChainShortcutsMap['wallet_switchEthereumChain'].find((shortcut) => Number(shortcut.data.chainId) === hexToNumber(chainId))?.data.chain ?? mainnet;

const verifyResult = await verifySignMsg({
method,
from: data.address?.toLowerCase(),
sign: response,
message: data.message,
chain: chain as Chain
});
if (verifyResult) {
setVerifyResult(verifyResult);
return;
}
}, []);
}, [provider]);

const submit = useCallback(
async (data: Record<string, string>) => {
Expand Down
80 changes: 33 additions & 47 deletions src/components/RpcMethods/method/signMessageMethods.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
import {
MessageTypes,
recoverPersonalSignature,
recoverTypedSignature,
SignTypedDataVersion,
TypedDataV1,
TypedMessage,
} from '@metamask/eth-sig-util';
import { Chain, createPublicClient, http, TypedDataDomain } from 'viem';

import { parseMessage } from '../shortcut/ShortcutType';
import { RpcRequestInput } from './RpcRequestInput';
Expand Down Expand Up @@ -69,64 +62,57 @@ export const signMessageMethods = [
ethSignTypedDataV4,
];

export const verifySignMsg = ({
export const verifySignMsg = async ({
method,
from,
sign,
message,
chain,
}: {
method: string;
from: string;
sign: string;
message: unknown;
chain: Chain;
}) => {
switch (method) {
case 'personal_sign': {
const msg = `0x${Buffer.from(message as string, 'utf8').toString('hex')}`;
const recoveredAddr = recoverPersonalSignature({
data: msg,
signature: sign,
const client = createPublicClient({
chain,
transport: http(),
});
if (recoveredAddr === from) {
return `SigUtil Successfully verified signer as ${recoveredAddr}`;
} else {
return `SigUtil Failed to verify signer when comparing ${recoveredAddr} to ${from}`;
}
}
case 'eth_signTypedData_v1': {
const recoveredAddr = recoverTypedSignature({
data: message as TypedDataV1,
signature: sign,
version: SignTypedDataVersion.V1,
});
if (recoveredAddr === from) {
return `SigUtil Successfully verified signer as ${recoveredAddr}`;
} else {
return `SigUtil Failed to verify signer when comparing ${recoveredAddr} to ${from}`;
}
}
case 'eth_signTypedData_v3': {
const recoveredAddr = recoverTypedSignature({
data: message as TypedMessage<MessageTypes>,
signature: sign,
version: SignTypedDataVersion.V3,
});
if (recoveredAddr === from) {
return `SigUtil Successfully verified signer as ${recoveredAddr}`;

const valid = await client.verifyMessage({
address: from as `0x${string}`,
message: message as string,
signature: sign as `0x${string}`,
})
if (valid) {
return `SigUtil Successfully verified signer as ${from}`;
} else {
return `SigUtil Failed to verify signer when comparing ${recoveredAddr} to ${from}`;
return `SigUtil Failed to verify signer`;
}
}
case 'eth_signTypedData_v1':
case 'eth_signTypedData_v3':
case 'eth_signTypedData_v4': {
const recoveredAddr = recoverTypedSignature({
data: message as TypedMessage<MessageTypes>,
signature: sign,
version: SignTypedDataVersion.V4,
const client = createPublicClient({
chain,
transport: http(),
});
if (recoveredAddr === from) {
return `SigUtil Successfully verified signer as ${recoveredAddr}`;

const valid = await client.verifyTypedData({
address: from as `0x${string}`,
domain: message['domain'] as TypedDataDomain,
types: message['types'] as any,
primaryType: message['primaryType'] as string,
message: message['message'] as any,
signature: sign as `0x${string}`,
})
if (valid) {
return `SigUtil Successfully verified signer as ${from}`;
} else {
return `SigUtil Failed to verify signer when comparing ${recoveredAddr} to ${from}`;
return `SigUtil Failed to verify signer`;
}
}
default:
Expand Down
5 changes: 5 additions & 0 deletions src/components/RpcMethods/shortcut/multipleChainShortcuts.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,33 @@
import { base, baseSepolia, harmonyOne, mainnet } from 'viem/chains';
import { ShortcutType } from './ShortcutType';

const walletSwitchEthereumChainShortcuts: ShortcutType[] = [
{
key: 'Ethereum',
data: {
chainId: '1',
chain: mainnet,
},
},
{
key: 'Base',
data: {
chainId: '8453',
chain: base,
},
},
{
key: 'Base Sepolia',
data: {
chainId: '84532',
chain: baseSepolia,
},
},
{
key: 'Harmony',
data: {
chainId: '1666600000',
chain: harmonyOne,
},
},
];
Expand Down
8 changes: 8 additions & 0 deletions src/pages/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@ export default function Home() {
});
}, [provider]);

useEffect(() => {
if (connected) {
provider?.request({ method: "eth_chainId"}).then((chainId) => {
setChainId(parseInt(chainId, 16));
});
}
}, [connected, provider]);

return (
<Container maxW={WIDTH_2XL} mb={8}>
<Box>
Expand Down
Loading

0 comments on commit c8040d5

Please sign in to comment.