Personal Signatures
Personal Signatures
Magic offers out-of-the-box UI when the user is prompted to sign a personal or typed message for the following EVM RPC methods:
-
personal_sign
signTypedData_v3
signTypedData_v4
These methods allow dapps to verfiably prove the ownership of the user's account through getting a signature from their private key and using it to sign arbitrary and/or typed data. It is also possible to get a signature from the user during login (in one step) through our login with verfication feature.
#Use Cases
- Used to prove verifiable ownership of a public address through signging arbitirary data provided by the dapp.
- Used in various scenarios where a user needs to sign a structured message as proof of their approval.
#Usage
After following the quickstart to ensure Magic SDK is setup correctly and the user has succcesfully logged in, you can then request consent to collect their information as follows:
Personal Signature (personal_sign
)
01import Web3 from "web3";
02import { Magic } from "magic-sdk";
03import { recoverPersonalSignature } from "@metamask/eth-sig-util";
04
05const magic = new Magic("YOUR_API_KEY", {
06 network: "goerli",
07});
08const web3 = new Web3(magic.rpcProvider);
09
10const signAndVerify = async () => {
11 const signedMessage = await web3.eth.personal.sign(
12 "Here is a basic message!",
13 account,
14 ""
15 );
16 console.log("signedMessage:", signedMessage);
17 // recover the public address of the signer to verify
18 const recoveredAddress = recoverPersonalSignature({
19 data: message,
20 signature: signedMessage,
21 });
22 console.log(
23 recoveredAddress.toLocaleLowerCase() === account.toLocaleLowerCase()
24 ? "Signing success!"
25 : "Signing failed!"
26 );
27};
Typed Data V3 (signTypedData_v3
)
01import Web3 from "web3";
02import { Magic } from "magic-sdk";
03import { recoverTypedSignature } from "@metamask/eth-sig-util";
04
05const magic = new Magic("YOUR_API_KEY", {
06 network: "goerli",
07});
08const web3 = new Web3(magic.rpcProvider);
09
10export const signTypedDataV3Payload = {
11 types: {
12 EIP712Domain: [
13 {
14 name: "name",
15 type: "string",
16 },
17 {
18 name: "version",
19 type: "string",
20 },
21 {
22 name: "verifyingContract",
23 type: "address",
24 },
25 ],
26 Greeting: [
27 {
28 name: "contents",
29 type: "string",
30 },
31 ],
32 },
33 primaryType: "Greeting",
34 domain: {
35 name: "Magic",
36 version: "1",
37 verifyingContract: "0xE0cef4417a772512E6C95cEf366403839b0D6D6D",
38 },
39 message: {
40 contents: "Hello, from Magic!",
41 },
42};
43
44const signAndVerify = async () => {
45 const params = [account, signTypedDataV3Payload];
46 const method = "eth_signTypedData_v4";
47 const signature = await magic.rpcProvider.request({
48 method,
49 params,
50 });
51 console.log("signature:", signature);
52 // recover the public address of the signer to verify
53 const recoveredAddress = recoverTypedSignature({
54 data: signTypedDataV3Payload,
55 signature,
56 version: "V3",
57 });
58
59 console.log(
60 recoveredAddress.toLocaleLowerCase() === account.toLocaleLowerCase()
61 ? "Signing success!"
62 : "Signing failed!"
63 );
64};
Typed Data V4 (signTypedData_v4
)
01import Web3 from "web3";
02import { Magic } from "magic-sdk";
03import { recoverPersonalSignature } from "@metamask/eth-sig-util";
04
05const magic = new Magic("YOUR_API_KEY", {
06 network: "goerli",
07});
08const web3 = new Web3(magic.rpcProvider);
09
10export const signTypedDataV4Payload = {
11 domain: {
12 // Defining the chain aka Rinkeby goerli or Ethereum Main Net
13 chainId: 5,
14 // Give a user friendly name to the specific contract you are signing for.
15 name: "Ether Mail",
16 // If name isn't enough add verifying contract to make sure you are establishing contracts with the proper entity
17 verifyingContract: "0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC",
18 // Just let's you know the latest version. Definitely make sure the field name is correct.
19 version: "1",
20 },
21
22 // Defining the message signing data content.
23 message: {
24 /*
25 - Anything you want. Just a JSON Blob that encodes the data you want to send
26 - No required fields
27 - This is DApp Specific
28 - Be as explicit as possible when building out the message schema.
29 */
30 contents: "Hello, Bob!",
31 attachedMoneyInEth: 4.2,
32 from: {
33 name: "Cow",
34 wallets: [
35 "0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826",
36 "0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF",
37 ],
38 },
39 to: [
40 {
41 name: "Bob",
42 wallets: [
43 "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB",
44 "0xB0BdaBea57B0BDABeA57b0bdABEA57b0BDabEa57",
45 "0xB0B0b0b0b0b0B000000000000000000000000000",
46 ],
47 },
48 ],
49 },
50 // Refers to the keys of the *types* object below.
51 primaryType: "Mail",
52 types: {
53 // TODO: Clarify if EIP712Domain refers to the domain the contract is hosted on
54 EIP712Domain: [
55 { name: "name", type: "string" },
56 { name: "version", type: "string" },
57 { name: "chainId", type: "uint256" },
58 { name: "verifyingContract", type: "address" },
59 ],
60 // Not an EIP712Domain definition
61 Group: [
62 { name: "name", type: "string" },
63 { name: "members", type: "Person[]" },
64 ],
65 // Refer to PrimaryType
66 Mail: [
67 { name: "from", type: "Person" },
68 { name: "to", type: "Person[]" },
69 { name: "contents", type: "string" },
70 ],
71 // Not an EIP712Domain definition
72 Person: [
73 { name: "name", type: "string" },
74 { name: "wallets", type: "address[]" },
75 ],
76 },
77};
78
79const signAndVerify = async () => {
80 const params = [account, signTypedDataV3Payload];
81 const method = "eth_signTypedData_v4";
82 const signature = await magic.rpcProvider.request({
83 method,
84 params,
85 });
86 console.log("signature:", signature);
87 // recover the public address of the signer to verify
88 const recoveredAddress = recoverTypedSignature({
89 data: signTypedDataV3Payload,
90 signature,
91 version: "V4",
92 });
93
94 console.log(
95 recoveredAddress.toLocaleLowerCase() === account.toLocaleLowerCase()
96 ? "Signing success!"
97 : "Signing failed!"
98 );
99};
#Configuration
- See how to brand this experience with your own logo and colors in the customization section.
#Reference
- Supported EVM RPC Methods