How to Integrate with the Ethereum Blockchain with Magic in Javascript

How to Integrate with the Ethereum Blockchain with Magic in Javascript

Installation

To interact with the Ethereum blockchain, you can use either ethers.js or web3.js libraries with Magic.

note

If you are already familiar with Ethereum application development, you can skip straight to our kitchen sink examples:

👉 Ethers.js Example
👉 Web3.js Example

Ethers.js

NPM

npm install --save ethers

Yarn

yarn add ethers

CDN

<script src="https://cdn.ethers.io/scripts/ethers-v4.min.js"></script>

Web3.js

NPM

npm install --save web3

Yarn

yarn add web3

CDN

<script src="https://cdn.jsdelivr.net/npm/web3@latest/dist/web3.min.js"></script>

Initializing Provider

important

Ethereum provider is only supported in magic-sdk@1.0.1 or later versions.

Ethers.js

ES Modules/TypeScript

import { Magic } from 'magic-sdk'; import { ethers } from 'ethers'; // Test key defaults to "rinkeby", live key defaults to "mainnet" const magic = new Magic('YOUR_PUBLISHABLE_API_KEY'); const provider = new ethers.providers.Web3Provider(magic.rpcProvider);

CommonJS

const { Magic } = require('magic-sdk'); const ethers = require('ethers'); // Test key defaults to "rinkeby", live key defaults to "mainnet" const magic = new Magic('YOUR_PUBLISHABLE_API_KEY'); const provider = new ethers.providers.Web3Provider(magic.rpcProvider);

Web3.js

ES Modules/TypeScript

import { Magic } from 'magic-sdk'; import Web3 from 'web3'; // Test key defaults to "rinkeby", live key defaults to "mainnet" const magic = new Magic('YOUR_PUBLISHABLE_API_KEY'); const web3 = new Web3(magic.rpcProvider); // Or window.web3 = ...

CommonJS

const { Magic } = require('magic-sdk'); const Web3 = require('web3'); // Test key defaults to "rinkeby", live key defaults to "mainnet" const magic = new Magic('YOUR_PUBLISHABLE_API_KEY'); const web3 = new Web3(magic.rpcProvider); // Or window.web3 = ...

Use Different Networks

Choose Different Testnet

const magic = new Magic('YOUR_PUBLISHABLE_API_KEY', { network: 'ropsten', // Supports "rinkeby", "ropsten", "kovan" });

Configure Custom Nodes

const customNodeOptions = { rpcUrl: 'http://127.0.0.1:7545', // Your own node URL chainId: 1011, // Your own node's chainId }; // Setting network to localhost blockchain const magic = new Magic('YOUR_PUBLISHABLE_API_KEY', { network: customNodeOptions, });

Get User Info

Ethers.js

import { Magic } from 'magic-sdk'; import { ethers } from 'ethers'; const magic = new Magic('YOUR_PUBLISHABLE_API_KEY'); const provider = new ethers.providers.Web3Provider(magic.rpcProvider); // ⭐️ After user is successfully authenticated const signer = provider.getSigner(); // Get user's Ethereum public address const address = await signer.getAddress(); // Get user's balance in ether const balance = ethers.utils.formatEther( await provider.getBalance(userAddress), // Balance is in wei );

Web3.js

note

Example is using web3@1.2.0 or later version.

import { Magic } from 'magic-sdk'; import Web3 from 'web3'; const magic = new Magic('YOUR_PUBLISHABLE_API_KEY'); const web3 = new Web3(magic.rpcProvider); // ⭐️ After user is successfully authenticated // Get user's Ethereum public address const address = (await web3.eth.getAccounts())[0]; // Get user's balance in ether const balance = web3.utils.fromWei( await web3.eth.getBalance(address), // Balance is in wei );

Send Transaction

Ethers.js

import { Magic } from 'magic-sdk'; import { ethers } from 'ethers'; const magic = new Magic('YOUR_PUBLISHABLE_API_KEY'); const provider = new ethers.providers.Web3Provider(magic.rpcProvider); // ⭐️ After user is successfully authenticated const signer = provider.getSigner(); const destination = '0xE0cef4417a772512E6C95cEf366403839b0D6D6D'; const amount = ethers.utils.parseEther('1.0'); // Convert 1 ether to wei // Submit transaction to the blockchain const tx = await signer.sendTransaction({ to: destination, value: amount, }); // Wait for transaction to be mined const receipt = await tx.wait();

Web3.js

note

Example is using web3@1.2.0 or later version.

import { Magic } from 'magic-sdk'; import Web3 from 'web3'; const magic = new Magic('YOUR_PUBLISHABLE_API_KEY'); const web3 = new Web3(magic.rpcProvider); // ⭐️ After user is successfully authenticated // Get user's Ethereum public address const fromAddress = (await web3.eth.getAccounts())[0]; const destination = '0xE0cef4417a772512E6C95cEf366403839b0D6D6D'; const amount = web3.utils.toWei(1); // Convert 1 ether to wei // Submit transaction to the blockchain and wait for it to be mined const receipt = await web3.eth.sendTransaction({ from: fromAddress, to: destination, value: amount, });

Sign Message

Ethers.js

Personal Sign

import { Magic } from 'magic-sdk'; import { ethers } from 'ethers'; const magic = new Magic('YOUR_PUBLISHABLE_API_KEY'); const provider = new ethers.providers.Web3Provider(magic.rpcProvider); // ⭐️ After user is successfully authenticated const signer = provider.getSigner(); const originalMessage = 'YOUR_MESSAGE'; const signedMessage = await signer.signMessage(originalMessage);

Sign Typed Data v1

import { Magic } from 'magic-sdk'; import { ethers } from 'ethers'; const magic = new Magic('YOUR_PUBLISHABLE_API_KEY'); const provider = new ethers.providers.Web3Provider(magic.rpcProvider); // ⭐️ After user is successfully authenticated // Get user's Ethereum public address const fromAddress = await signer.getAddress(); const originalMessage = [ { type: 'string', name: 'fullName', value: 'John Doe', }, { type: 'uint32', name: 'userId', value: '1234', }, ]; const params = [originalMessage, fromAddress]; const method = 'eth_signTypedData'; const signedMessage = await signer.provider.send(method, params);

Sign Typed Data v3

import { Magic } from 'magic-sdk'; import { ethers } from 'ethers'; const magic = new Magic('YOUR_PUBLISHABLE_API_KEY'); const provider = new ethers.providers.Web3Provider(magic.rpcProvider); // ⭐️ After user is successfully authenticated // Get user's Ethereum public address const fromAddress = await signer.getAddress(); const originalMessage = { types: { EIP712Domain: [ { name: 'name', type: 'string', }, { name: 'version', type: 'string', }, { name: 'verifyingContract', type: 'address', }, ], Greeting: [ { name: 'contents', type: 'string', }, ], }, primaryType: 'Greeting', domain: { name: 'Magic', version: '1', verifyingContract: '0xE0cef4417a772512E6C95cEf366403839b0D6D6D', }, message: { contents: 'Hello, from Magic!', }, }; const params = [fromAddress, originalMessage]; const method = 'eth_signTypedData_v3'; const signedMessage = await signer.provider.send(method, params);

Sign Typed Data v4

/* Sign Typed Data v4 adds support for arrays and recursive data types. Otherwise, it works the same as Sign Typed Data v3. */ import { Magic } from 'magic-sdk'; import { ethers } from 'ethers'; const magic = new Magic('YOUR_PUBLISHABLE_API_KEY'); const provider = new ethers.providers.Web3Provider(magic.rpcProvider); // ⭐️ After user is successfully authenticated // Get user's Ethereum public address const fromAddress = await signer.getAddress(); const originalMessage = { types: { EIP712Domain: [ { name: 'name', type: 'string', }, { name: 'version', type: 'string', }, { name: 'verifyingContract', type: 'address', }, ], Greeting: [ { name: 'contents', type: 'string', }, ], }, primaryType: 'Greeting', domain: { name: 'Magic', version: '1', verifyingContract: '0xE0cef4417a772512E6C95cEf366403839b0D6D6D', }, message: { contents: 'Hello, from Magic!', }, }; const params = [fromAddress, originalMessage]; const method = 'eth_signTypedData_v4'; const signedMessage = await signer.provider.send(method, params);

Web3.js

note

The following examples assume web3@>=1.2.0

Personal Sign

import { Magic } from 'magic-sdk'; import Web3 from 'web3'; const magic = new Magic('YOUR_PUBLISHABLE_API_KEY'); const web3 = new Web3(magic.rpcProvider); // ⭐️ After user is successfully authenticated // Get user's Ethereum public address const fromAddress = (await web3.eth.getAccounts())[0]; const originalMessage = 'YOUR_MESSAGE'; const signedMessage = await web3.eth.personal.sign(originalMessage, fromAddress);

Sign Typed Data v1

import { Magic } from 'magic-sdk'; import Web3 from 'web3'; const magic = new Magic('YOUR_PUBLISHABLE_API_KEY'); const web3 = new Web3(magic.rpcProvider); // ⭐️ After user is successfully authenticated // Get user's Ethereum public address const fromAddress = (await web3.eth.getAccounts())[0]; const originalMessage = [ { type: 'string', name: 'fullName', value: 'John Doe', }, { type: 'uint32', name: 'userId', value: '1234', }, ]; const params = [originalMessage, fromAddress]; const method = 'eth_signTypedData'; const signedMessage = await web3.currentProvider.sendAsync({ id: 1, method, params, fromAddress, });

Sign Typed Data v3

import { Magic } from 'magic-sdk'; import Web3 from 'web3'; const magic = new Magic('YOUR_PUBLISHABLE_API_KEY'); const web3 = new Web3(magic.rpcProvider); // ⭐️ After user is successfully authenticated // Get user's Ethereum public address const fromAddress = (await web3.eth.getAccounts())[0]; const originalMessage = { types: { EIP712Domain: [ { name: 'name', type: 'string', }, { name: 'version', type: 'string', }, { name: 'verifyingContract', type: 'address', }, ], Greeting: [ { name: 'contents', type: 'string', }, ], }, primaryType: 'Greeting', domain: { name: 'Magic', version: '1', verifyingContract: '0xE0cef4417a772512E6C95cEf366403839b0D6D6D', }, message: { contents: 'Hello, from Magic!', }, }; const params = [fromAddress, originalMessage]; const method = 'eth_signTypedData_v3'; const signedMessage = await web3.currentProvider.sendAsync({ id: 1, method, params, fromAddress, });

Sign Typed Data v4

/* Sign Typed Data v4 adds support for arrays and recursive data types. Otherwise, it works the same as Sign Typed Data v3. */ import { Magic } from 'magic-sdk'; import Web3 from 'web3'; const magic = new Magic('YOUR_PUBLISHABLE_API_KEY'); const web3 = new Web3(magic.rpcProvider); // ⭐️ After user is successfully authenticated // Get user's Ethereum public address const fromAddress = (await web3.eth.getAccounts())[0]; const originalMessage = { types: { EIP712Domain: [ { name: 'name', type: 'string', }, { name: 'version', type: 'string', }, { name: 'verifyingContract', type: 'address', }, ], Greeting: [ { name: 'contents', type: 'string', }, ], }, primaryType: 'Greeting', domain: { name: 'Magic', version: '1', verifyingContract: '0xE0cef4417a772512E6C95cEf366403839b0D6D6D', }, message: { contents: 'Hello, from Magic!', }, }; const params = [fromAddress, originalMessage]; const method = 'eth_signTypedData_v4'; const signedMessage = await web3.currentProvider.sendAsync({ id: 1, method, params, fromAddress, });

Smart Contract

Solidity 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.

pragma solidity ^0.5.10; contract HelloWorld { string public message; constructor(string memory initMessage) public { message = initMessage; } function update(string memory newMessage) public { message = newMessage; } }

Ethers.js

Deploy Contract

import { Magic } from 'magic-sdk'; import { ethers } from 'ethers'; const magic = new Magic('YOUR_PUBLISHABLE_API_KEY'); const provider = new ethers.providers.Web3Provider(magic.rpcProvider); // ⭐️ After user is successfully authenticated const signer = provider.getSigner(); const contractABI = '[{"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"}]'; const contractByteCode = '0x608060405234801561001057600080fd5b5060405161047f38038061047f8339818101604052602081101561003357600080fd5b81019080805164010000000081111561004b57600080fd5b8281019050602081018481111561006157600080fd5b815185600182028301116401000000008211171561007e57600080fd5b5050929190505050806000908051906020019061009c9291906100a3565b5050610148565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106100e457805160ff1916838001178555610112565b82800160010185558215610112579182015b828111156101115782518255916020019190600101906100f6565b5b50905061011f9190610123565b5090565b61014591905b80821115610141576000816000905550600101610129565b5090565b90565b610328806101576000396000f3fe608060405234801561001057600080fd5b5060043610610053576000357c0100000000000000000000000000000000000000000000000000000000900480633d7403a314610058578063e21f37ce14610113575b600080fd5b6101116004803603602081101561006e57600080fd5b810190808035906020019064010000000081111561008b57600080fd5b82018360208201111561009d57600080fd5b803590602001918460018302840111640100000000831117156100bf57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050610196565b005b61011b6101b0565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561015b578082015181840152602081019050610140565b50505050905090810190601f1680156101885780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b80600090805190602001906101ac92919061024e565b5050565b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156102465780601f1061021b57610100808354040283529160200191610246565b820191906000526020600020905b81548152906001019060200180831161022957829003601f168201915b505050505081565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061028f57805160ff19168380011785556102bd565b828001600101855582156102bd579182015b828111156102bc5782518255916020019190600101906102a1565b5b5090506102ca91906102ce565b5090565b6102f091905b808211156102ec5760008160009055506001016102d4565b5090565b9056fea265627a7a7230582003ae1ef5a63bf058bfd2b31398bdee39d3cbfbb7fbf84235f4bc2ec352ee810f64736f6c634300050a0032'; const contractFactory = new ethers.ContractFactory(contractABI, contractByteCode, signer); // Deploy contract with "Hello World!" in the constructor const contract = await contractFactory.deploy('Hello World!'); // Wait for deployment to finish const receipt = await contract.deployed();

Read From Contract

import { Magic } from 'magic-sdk'; import { ethers } from 'ethers'; const magic = new Magic('YOUR_PUBLISHABLE_API_KEY'); const provider = new ethers.providers.Web3Provider(magic.rpcProvider); // ⭐️ After user is successfully authenticated const signer = provider.getSigner(); const contractABI = '[{"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"}]'; const contractAddress = '0x8b211dfebf490a648f6de859dfbed61fa22f35e0'; const contract = new ethers.Contract(contractAddress, contractABI, signer); // Read message from smart contract const message = await contract.message();

Write to Contract

import { Magic } from 'magic-sdk'; import { ethers } from 'ethers'; const magic = new Magic('YOUR_PUBLISHABLE_API_KEY'); const provider = new ethers.providers.Web3Provider(magic.rpcProvider); // ⭐️ After user is successfully authenticated const signer = provider.getSigner(); const contractABI = '[{"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"}]'; const contractAddress = '0x8b211dfebf490a648f6de859dfbed61fa22f35e0'; const contract = new ethers.Contract(contractAddress, contractABI, signer); // Send transaction to smart contract to update message const tx = await contract.update('NEW_MESSAGE'); // Wait for transaction to finish const receipt = await tx.wait();

Web3.js

note

Example is using web3@1.2.0 or later version.

Deploy Contract

import { Magic } from 'magic-sdk'; import Web3 from 'web3'; const magic = new Magic('YOUR_PUBLISHABLE_API_KEY'); const web3 = new Web3(magic.rpcProvider); // ⭐️ After user is successfully authenticated // Get user's Ethereum public address const fromAddress = (await web3.eth.getAccounts())[0]; const contractABI = '[{"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"}]'; const contractByteCode = '0x608060405234801561001057600080fd5b5060405161047f38038061047f8339818101604052602081101561003357600080fd5b81019080805164010000000081111561004b57600080fd5b8281019050602081018481111561006157600080fd5b815185600182028301116401000000008211171561007e57600080fd5b5050929190505050806000908051906020019061009c9291906100a3565b5050610148565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106100e457805160ff1916838001178555610112565b82800160010185558215610112579182015b828111156101115782518255916020019190600101906100f6565b5b50905061011f9190610123565b5090565b61014591905b80821115610141576000816000905550600101610129565b5090565b90565b610328806101576000396000f3fe608060405234801561001057600080fd5b5060043610610053576000357c0100000000000000000000000000000000000000000000000000000000900480633d7403a314610058578063e21f37ce14610113575b600080fd5b6101116004803603602081101561006e57600080fd5b810190808035906020019064010000000081111561008b57600080fd5b82018360208201111561009d57600080fd5b803590602001918460018302840111640100000000831117156100bf57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050610196565b005b61011b6101b0565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561015b578082015181840152602081019050610140565b50505050905090810190601f1680156101885780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b80600090805190602001906101ac92919061024e565b5050565b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156102465780601f1061021b57610100808354040283529160200191610246565b820191906000526020600020905b81548152906001019060200180831161022957829003601f168201915b505050505081565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061028f57805160ff19168380011785556102bd565b828001600101855582156102bd579182015b828111156102bc5782518255916020019190600101906102a1565b5b5090506102ca91906102ce565b5090565b6102f091905b808211156102ec5760008160009055506001016102d4565b5090565b9056fea265627a7a7230582003ae1ef5a63bf058bfd2b31398bdee39d3cbfbb7fbf84235f4bc2ec352ee810f64736f6c634300050a0032'; const contract = new web3.eth.Contract(JSON.parse(contractABI)); // Deploy contract with "Hello World!" in the constructor and wait to finish const contractInstance = await contract .deploy({ data: contractByteCode, arguments: ['Hello World!'], }) .send({ from: fromAddress, });

Read From Contract

import { Magic } from 'magic-sdk'; import Web3 from 'web3'; const magic = new Magic('YOUR_PUBLISHABLE_API_KEY'); const web3 = new Web3(magic.rpcProvider); // ⭐️ After user is successfully authenticated // Get user's Ethereum public address const fromAddress = (await web3.eth.getAccounts())[0]; const contractABI = '[{"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"}]'; const contractAddress = '0x8b211dfebf490a648f6de859dfbed61fa22f35e0'; const contract = new web3.eth.Contract(JSON.parse(contractABI), contractAddress); // Read message from smart contract const message = await contract.methods.message().call();

Write to Contract

import { Magic } from 'magic-sdk'; import Web3 from 'web3'; const magic = new Magic('YOUR_PUBLISHABLE_API_KEY'); const web3 = new Web3(magic.rpcProvider); // ⭐️ After user is successfully authenticated // Get user's Ethereum public address const fromAddress = (await web3.eth.getAccounts())[0]; const contractABI = '[{"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"}]'; const contractAddress = '0x8b211dfebf490a648f6de859dfbed61fa22f35e0'; const contract = new web3.eth.Contract(JSON.parse(contractABI), contractAddress); // Send transaction to smart contract to update message and wait to finish const receipt = await contract.methods.update('NEW_MESSAGE').send({ from: fromAddress });