How to Integrate with the Ethereum Blockchain using Javascript
How to Integrate with the Ethereum Blockchain using Javascript
#Installation
To interact with the EVM network, you can use either ethers.js
or web3.js
libraries with Magic.
To get started, install the following dependencies for your project:
#Ethers.js
01npm install ethers magic-sdk
#Web3.js
01npm install web3 magic-sdk
#Initialization
The Magic class is the entry-point to the Magic SDK. It must be instantiated with a Magic publishable key.
Ethereum provider is only supported in magic-sdk@1.0.1 or later versions.
#Ethers.js
#ES Modules/TypeScript
01import { Magic } from 'magic-sdk';
02import { ethers } from 'ethers';
03
04const magic = new Magic('YOUR_PUBLISHABLE_API_KEY');
05const provider = new ethers.BrowserProvider(magic.rpcProvider);
#CommonJS
01const { Magic } = require('magic-sdk');
02const ethers = require('ethers');
03
04const magic = new Magic('YOUR_PUBLISHABLE_API_KEY');
05const provider = new ethers.BrowserProvider(magic.rpcProvider);
#Web3.js
#ES Modules/TypeScript
01import { Magic } from 'magic-sdk';
02import Web3 from 'web3';
03
04const magic = new Magic('YOUR_PUBLISHABLE_API_KEY');
05const web3 = new Web3(magic.rpcProvider); // Or window.web3 = ...
#CommonJS
01const { Magic } = require('magic-sdk');
02const Web3 = require('web3');
03
04const magic = new Magic('YOUR_PUBLISHABLE_API_KEY');
05const web3 = new Web3(magic.rpcProvider); // Or window.web3 = ...
#Mainnet
Mainnet Block Explorer: https://etherscan.io
01const magic = new Magic('YOUR_PUBLISHABLE_API_KEY', {
02 network: 'mainnet',
03});
04
05// Magic's node infrastructure maps 'mainnet' and 'testnet' to 2 unique set of addresses.
#Testnet
Sepolia Block Explorer: https://sepolia.etherscan.io/
Sepolia Testnet Faucet: https://sepoliafaucet.com/
01const magic = new Magic('YOUR_PUBLISHABLE_API_KEY', {
02 network: 'sepolia',
03});
04
05// Magic's node infrastructure maps 'mainnet' and 'sepolia' to 2 unique set of addresses.
#Custom Node
You can allow specific URLs to interact with the Magic SDK, such as a custom RPC URL to send transactions to your node. The Content Security Policy (CSP) of a browser dictates what resources can be loaded. If you're using a Dedicated Wallet, you can update the policy in the settings page of the dashboard with your custom URL. If you're using a Universal Wallet, please reach out to support to get your URL added.
The use of a custom node will require the RPC URL to the project's Content Security Policy from your Magic dashboard. Refer to the CSP documentation.
01const customNodeOptions = {
02 rpcUrl: 'http://127.0.0.1:7545', // Your own node URL
03 chainId: 1011, // Your own node's chainId
04};
05
06// Setting network to localhost blockchain
07const magic = new Magic('YOUR_PUBLISHABLE_API_KEY', {
08 network: customNodeOptions,
09});
10
11// This configuration will map addresses in line with Magic's 'mainnet' setup.
#Common Methods
All Web.js examples are using web3@1.2.0 or later version.
#Send Transaction
#Ethers.js
01import { Magic } from 'magic-sdk';
02import { ethers } from 'ethers';
03
04const magic = new Magic('YOUR_PUBLISHABLE_API_KEY');
05const provider = new ethers.BrowserProvider(magic.rpcProvider);
06
07// ⭐️ After user is successfully authenticated
08
09const signer = await provider.getSigner();
10
11const destination = '0xE0cef4417a772512E6C95cEf366403839b0D6D6D';
12const amount = ethers.parseEther('1.0'); // Convert 1 ether to wei
13
14// Submit transaction to the blockchain
15const tx = await signer.sendTransaction({
16 to: destination,
17 value: amount,
18});
19
20// Wait for transaction to be mined
21const receipt = await tx.wait();
#Web3.js
01import { Magic } from 'magic-sdk';
02import Web3 from 'web3';
03
04const magic = new Magic('YOUR_PUBLISHABLE_API_KEY');
05const web3 = new Web3(magic.rpcProvider);
06
07// ⭐️ After user is successfully authenticated
08
09// Get user's Ethereum public address
10const fromAddress = (await web3.eth.getAccounts())[0];
11
12const destination = '0xE0cef4417a772512E6C95cEf366403839b0D6D6D';
13const amount = web3.utils.toWei(1); // Convert 1 ether to wei
14
15// Submit transaction to the blockchain and wait for it to be mined
16const receipt = await web3.eth.sendTransaction({
17 from: fromAddress,
18 to: destination,
19 value: amount,
20});
#Sign Message
#Ethers.js
Personal Sign
01import { Magic } from 'magic-sdk';
02import { ethers } from 'ethers';
03
04const magic = new Magic('YOUR_PUBLISHABLE_API_KEY');
05const provider = new ethers.BrowserProvider(magic.rpcProvider);
06
07// ⭐️ After user is successfully authenticated
08
09const signer = await provider.getSigner();
10
11const originalMessage = 'YOUR_MESSAGE';
12const signedMessage = await signer.signMessage(originalMessage);
Sign Typed Data v1
01import { Magic } from 'magic-sdk';
02import { ethers } from 'ethers';
03
04const magic = new Magic('YOUR_PUBLISHABLE_API_KEY');
05const provider = new ethers.BrowserProvider(magic.rpcProvider);
06
07// ⭐️ After user is successfully authenticated
08
09const signer = await provider.getSigner();
10
11// Get user's Ethereum public address
12const fromAddress = await signer.getAddress();
13
14const originalMessage = [
15 {
16 type: 'string',
17 name: 'fullName',
18 value: 'John Doe',
19 },
20 {
21 type: 'uint32',
22 name: 'userId',
23 value: '1234',
24 },
25];
26const params = [originalMessage, fromAddress];
27const method = 'eth_signTypedData';
28
29const signedMessage = await signer.provider.send(method, params);
Sign Typed Data v3
01import { Magic } from 'magic-sdk';
02import { ethers } from 'ethers';
03
04const magic = new Magic('YOUR_PUBLISHABLE_API_KEY');
05const provider = new ethers.BrowserProvider(magic.rpcProvider);
06
07// ⭐️ After user is successfully authenticated
08
09const signer = await provider.getSigner();
10
11// Get user's Ethereum public address
12const fromAddress = await signer.getAddress();
13
14const originalMessage = {
15 types: {
16 EIP712Domain: [
17 {
18 name: 'name',
19 type: 'string',
20 },
21 {
22 name: 'version',
23 type: 'string',
24 },
25 {
26 name: 'verifyingContract',
27 type: 'address',
28 },
29 ],
30 Greeting: [
31 {
32 name: 'contents',
33 type: 'string',
34 },
35 ],
36 },
37 primaryType: 'Greeting',
38 domain: {
39 name: 'Magic',
40 version: '1',
41 verifyingContract: '0xE0cef4417a772512E6C95cEf366403839b0D6D6D',
42 },
43 message: {
44 contents: 'Hello, from Magic!',
45 },
46};
47const params = [fromAddress, originalMessage];
48const method = 'eth_signTypedData_v3';
49
50const signedMessage = await signer.provider.send(method, params);
Sign Typed Data v4
01/*
02 Sign Typed Data v4 adds support for
03 arrays and recursive data types.
04
05 Otherwise, it works the same as Sign Typed Data v3.
06 */
07
08import { Magic } from 'magic-sdk';
09import { ethers } from 'ethers';
10
11const magic = new Magic('YOUR_PUBLISHABLE_API_KEY');
12const provider = new ethers.BrowserProvider(magic.rpcProvider);
13
14// ⭐️ After user is successfully authenticated
15
16const signer = await provider.getSigner();
17
18// Get user's Ethereum public address
19const fromAddress = await signer.getAddress();
20
21const originalMessage = {
22 types: {
23 EIP712Domain: [
24 {
25 name: 'name',
26 type: 'string',
27 },
28 {
29 name: 'version',
30 type: 'string',
31 },
32 {
33 name: 'verifyingContract',
34 type: 'address',
35 },
36 ],
37 Greeting: [
38 {
39 name: 'contents',
40 type: 'string',
41 },
42 ],
43 },
44 primaryType: 'Greeting',
45 domain: {
46 name: 'Magic',
47 version: '1',
48 verifyingContract: '0xE0cef4417a772512E6C95cEf366403839b0D6D6D',
49 },
50 message: {
51 contents: 'Hello, from Magic!',
52 },
53};
54const params = [fromAddress, originalMessage];
55const method = 'eth_signTypedData_v4';
56
57const signedMessage = await signer.provider.send(method, params);
#Web3.js
Personal Sign
01import { Magic } from 'magic-sdk';
02import Web3 from 'web3';
03
04const magic = new Magic('YOUR_PUBLISHABLE_API_KEY');
05const web3 = new Web3(magic.rpcProvider);
06
07// ⭐️ After user is successfully authenticated
08
09// Get user's Ethereum public address
10const fromAddress = (await web3.eth.getAccounts())[0];
11
12const originalMessage = 'YOUR_MESSAGE';
13
14const signedMessage = await web3.eth.personal.sign(originalMessage, fromAddress);
Sign Typed Data v1
01import { Magic } from 'magic-sdk';
02import Web3 from 'web3';
03
04const magic = new Magic('YOUR_PUBLISHABLE_API_KEY');
05const web3 = new Web3(magic.rpcProvider);
06
07// ⭐️ After user is successfully authenticated
08
09// Get user's Ethereum public address
10const fromAddress = (await web3.eth.getAccounts())[0];
11
12const message = [
13 {
14 type: 'string',
15 name: 'fullName',
16 value: 'John Doe',
17 },
18 {
19 type: 'uint32',
20 name: 'userId',
21 value: '1234',
22 },
23];
24
25signedMessage = await web3.eth.signTypedData(fromAddress, message, true);
Sign Typed Data v4
01/*
02 Sign Typed Data v4 adds support for
03 arrays and recursive data types.
04
05 Otherwise, it works the same as Sign Typed Data v3.
06 */
07
08import { Magic } from 'magic-sdk';
09import Web3 from 'web3';
10
11const magic = new Magic('YOUR_PUBLISHABLE_API_KEY');
12const web3 = new Web3(magic.rpcProvider);
13
14// ⭐️ After user is successfully authenticated
15
16// Get user's Ethereum public address
17const fromAddress = (await web3.eth.getAccounts())[0];
18
19const message = {
20 types: {
21 EIP712Domain: [
22 {
23 name: 'name',
24 type: 'string',
25 },
26 {
27 name: 'version',
28 type: 'string',
29 },
30 {
31 name: 'verifyingContract',
32 type: 'address',
33 },
34 ],
35 Greeting: [
36 {
37 name: 'contents',
38 type: 'string',
39 },
40 ],
41 },
42 primaryType: 'Greeting',
43 domain: {
44 name: 'Magic',
45 version: '1',
46 verifyingContract: '0xE0cef4417a772512E6C95cEf366403839b0D6D6D',
47 },
48 message: {
49 contents: 'Hello, from Magic!',
50 },
51};
52
53const signedMessage = await web3.eth.signTypedData(fromAddress, message);
#Get Balance
#Ethers.js
01import { Magic } from 'magic-sdk';
02import { ethers } from 'ethers';
03
04const magic = new Magic('YOUR_PUBLISHABLE_API_KEY')
05const provider = new ethers.BrowserProvider(magic.rpcProvider);
06
07// ⭐️ After user is successfully authenticated
08
09const signer = await provider.getSigner();
10
11// Get user's Ethereum public address
12const address = await signer.getAddress();
13
14// Get user's balance in ether
15const balance = ethers.formatEther(
16 await provider.getBalance(address), // Balance is in wei
17);
#Web3.js
01import { Magic } from 'magic-sdk';
02import Web3 from 'web3';
03
04const magic = new Magic('YOUR_PUBLISHABLE_API_KEY');
05const web3 = new Web3(magic.rpcProvider);
06
07// ⭐️ After user is successfully authenticated
08
09// Get user's Ethereum public address
10const address = (await web3.eth.getAccounts())[0];
11
12// Get user's balance in ether
13const balance = web3.utils.fromWei(
14 await web3.eth.getBalance(address), // Balance is in wei
15);
#Smart Contract
In this example, we'll be demonstrating how to use Magic with ethers.js or web3.js to interact with Solidity smart contracts. The simple Hello World contract allows anyone to read and write a message to it.
01pragma solidity ^0.5.10;
02
03contract HelloWorld {
04
05 string public message;
06
07 constructor(string memory initMessage) public {
08 message = initMessage;
09 }
10
11 function update(string memory newMessage) public {
12 message = newMessage;
13 }
14}
#Deploy Contract
#Ethers.js
01import { Magic } from 'magic-sdk';
02import { ethers } from 'ethers';
03
04const magic = new Magic('YOUR_PUBLISHABLE_API_KEY');
05const provider = new ethers.BrowserProvider(magic.rpcProvider);
06
07// ⭐️ After user is successfully authenticated
08
09const signer = await provider.getSigner();
10
11const contractABI =
12'[{"constant":false,"inputs":[{"name":"newMessage","type":"string"}],"name":"update","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"message","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"initMessage","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]';
13
14const contractByteCode =
15 '0x608060405234801561001057600080fd5b5060405161047f38038061047f8339818101604052602081101561003357600080fd5b81019080805164010000000081111561004b57600080fd5b8281019050602081018481111561006157600080fd5b815185600182028301116401000000008211171561007e57600080fd5b5050929190505050806000908051906020019061009c9291906100a3565b5050610148565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106100e457805160ff1916838001178555610112565b82800160010185558215610112579182015b828111156101115782518255916020019190600101906100f6565b5b50905061011f9190610123565b5090565b61014591905b80821115610141576000816000905550600101610129565b5090565b90565b610328806101576000396000f3fe608060405234801561001057600080fd5b5060043610610053576000357c0100000000000000000000000000000000000000000000000000000000900480633d7403a314610058578063e21f37ce14610113575b600080fd5b6101116004803603602081101561006e57600080fd5b810190808035906020019064010000000081111561008b57600080fd5b82018360208201111561009d57600080fd5b803590602001918460018302840111640100000000831117156100bf57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050610196565b005b61011b6101b0565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561015b578082015181840152602081019050610140565b50505050905090810190601f1680156101885780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b80600090805190602001906101ac92919061024e565b5050565b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156102465780601f1061021b57610100808354040283529160200191610246565b820191906000526020600020905b81548152906001019060200180831161022957829003601f168201915b505050505081565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061028f57805160ff19168380011785556102bd565b828001600101855582156102bd579182015b828111156102bc5782518255916020019190600101906102a1565b5b5090506102ca91906102ce565b5090565b6102f091905b808211156102ec5760008160009055506001016102d4565b5090565b9056fea265627a7a7230582003ae1ef5a63bf058bfd2b31398bdee39d3cbfbb7fbf84235f4bc2ec352ee810f64736f6c634300050a0032';
16const contractFactory = new ethers.ContractFactory(contractABI, contractByteCode, signer);
17
18// Deploy contract with "Hello World!" in the constructor
19const contract = await contractFactory.deploy('Hello World!');
20// Wait for deployment to finish
21const receipt = contract.deploymentTransaction()
#Web3.js
01import { Magic } from 'magic-sdk';
02import Web3 from 'web3';
03
04const magic = new Magic('YOUR_PUBLISHABLE_API_KEY');
05const web3 = new Web3(magic.rpcProvider);
06
07// ⭐️ After user is successfully authenticated
08
09// Get user's Ethereum public address
10const fromAddress = (await web3.eth.getAccounts())[0];
11
12const contractABI =
13 '[{"constant":false,"inputs":[{"name":"newMessage","type":"string"}],"name":"update","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"message","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"initMessage","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]';
14const contractByteCode =
15 '0x608060405234801561001057600080fd5b5060405161047f38038061047f8339818101604052602081101561003357600080fd5b81019080805164010000000081111561004b57600080fd5b8281019050602081018481111561006157600080fd5b815185600182028301116401000000008211171561007e57600080fd5b5050929190505050806000908051906020019061009c9291906100a3565b5050610148565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106100e457805160ff1916838001178555610112565b82800160010185558215610112579182015b828111156101115782518255916020019190600101906100f6565b5b50905061011f9190610123565b5090565b61014591905b80821115610141576000816000905550600101610129565b5090565b90565b610328806101576000396000f3fe608060405234801561001057600080fd5b5060043610610053576000357c0100000000000000000000000000000000000000000000000000000000900480633d7403a314610058578063e21f37ce14610113575b600080fd5b6101116004803603602081101561006e57600080fd5b810190808035906020019064010000000081111561008b57600080fd5b82018360208201111561009d57600080fd5b803590602001918460018302840111640100000000831117156100bf57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050610196565b005b61011b6101b0565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561015b578082015181840152602081019050610140565b50505050905090810190601f1680156101885780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b80600090805190602001906101ac92919061024e565b5050565b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156102465780601f1061021b57610100808354040283529160200191610246565b820191906000526020600020905b81548152906001019060200180831161022957829003601f168201915b505050505081565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061028f57805160ff19168380011785556102bd565b828001600101855582156102bd579182015b828111156102bc5782518255916020019190600101906102a1565b5b5090506102ca91906102ce565b5090565b6102f091905b808211156102ec5760008160009055506001016102d4565b5090565b9056fea265627a7a7230582003ae1ef5a63bf058bfd2b31398bdee39d3cbfbb7fbf84235f4bc2ec352ee810f64736f6c634300050a0032';
16const contract = new web3.eth.Contract(JSON.parse(contractABI));
17
18// Deploy contract with "Hello World!" in the constructor and wait to finish
19const contractInstance = await contract
20 .deploy({
21 data: contractByteCode,
22 arguments: ['Hello World!'],
23 })
24 .send({
25 from: fromAddress,
26 });
#Read From Contract
#Ethers.js
01import { Magic } from 'magic-sdk';
02import { ethers } from 'ethers';
03
04const magic = new Magic('YOUR_PUBLISHABLE_API_KEY');
05const provider = new ethers.BrowserProvider(magic.rpcProvider);
06
07// ⭐️ After user is successfully authenticated
08
09const signer = await provider.getSigner();
10
11const contractABI =
12 '[{"constant":false,"inputs":[{"name":"newMessage","type":"string"}],"name":"update","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"message","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"initMessage","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]';
13const contractAddress = 'CONTRACT_ADDRESS';
14const contract = new ethers.Contract(contractAddress, contractABI, signer);
15
16// Read message from smart contract
17const message = await contract.message();
#Web3.js
01import { Magic } from 'magic-sdk';
02import Web3 from 'web3';
03
04const magic = new Magic('YOUR_PUBLISHABLE_API_KEY');
05const web3 = new Web3(magic.rpcProvider);
06
07// ⭐️ After user is successfully authenticated
08
09// Get user's Ethereum public address
10const fromAddress = (await web3.eth.getAccounts())[0];
11
12const contractABI =
13 '[{"constant":false,"inputs":[{"name":"newMessage","type":"string"}],"name":"update","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"message","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"initMessage","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]';
14const contractAddress = 'CONTRACT_ADDRESS';
15const contract = new web3.eth.Contract(JSON.parse(contractABI), contractAddress);
16
17// Read message from smart contract
18const message = await contract.methods.message().call();
#Write to Contract
#Ethers.js
01import { Magic } from 'magic-sdk';
02import { ethers } from 'ethers';
03
04const magic = new Magic('YOUR_PUBLISHABLE_API_KEY');
05const provider = new ethers.BrowserProvider(magic.rpcProvider);
06
07// ⭐️ After user is successfully authenticated
08
09const signer = await provider.getSigner();
10
11const contractABI =
12 '[{"constant":false,"inputs":[{"name":"newMessage","type":"string"}],"name":"update","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"message","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"initMessage","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]';
13const contractAddress = 'CONTRACT_ADDRESS';
14const contract = new ethers.Contract(contractAddress, contractABI, signer);
15
16// Send transaction to smart contract to update message
17const tx = await contract.update('NEW_MESSAGE');
18
19// Wait for transaction to finish
20const receipt = await tx.wait();
#Web3.js
01import { Magic } from 'magic-sdk';
02import Web3 from 'web3';
03
04const magic = new Magic('YOUR_PUBLISHABLE_API_KEY');
05const web3 = new Web3(magic.rpcProvider);
06
07// ⭐️ After user is successfully authenticated
08
09// Get user's Ethereum public address
10const fromAddress = (await web3.eth.getAccounts())[0];
11
12const contractABI =
13 '[{"constant":false,"inputs":[{"name":"newMessage","type":"string"}],"name":"update","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"message","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"initMessage","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"}]';
14const contractAddress = 'CONTRACT_ADDRESS';
15const contract = new web3.eth.Contract(JSON.parse(contractABI), contractAddress);
16
17// Send transaction to smart contract to update message and wait to finish
18const receipt = await contract.methods.update('NEW_MESSAGE').send({ from: fromAddress });