Installation

To interact with the EVM network, you will need to use a web3 provider library, such as ethers.js, with Magic. ⁠To get started, install the following dependencies for your project:

Ethers.js

npm install ethers magic-sdk

Initialization

The Magic class is the entry-point to the Magic SDK. It must be instantiated with a Magic publishable key.
ImportantEthereum provider is only supported in [email protected] or later versions.

Ethers.js

ES Modules/TypeScript
import { Magic } from "magic-sdk";
import { ethers } from "ethers";

const magic = new Magic('YOUR_PUBLISHABLE_API_KEY');
const provider = new ethers.BrowserProvider(magic.rpcProvider);
CommonJS
const { Magic } = require('magic-sdk');
const ethers = require('ethers');

const magic = new Magic('YOUR_PUBLISHABLE_API_KEY');
const provider = new ethers.BrowserProvider(magic.rpcProvider);

Mainnet

Mainnet Block Explorer: https://etherscan.io
JavaScript
const magic = new Magic('YOUR_PUBLISHABLE_API_KEY', {
  network: 'mainnet',
});

// 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/
JavaScript
const magic = new Magic('YOUR_PUBLISHABLE_API_KEY', {
  network: 'sepolia',
});

// 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. You can update the policy in the settings page of the dashboard with your custom URL.
ImportantThe 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.
JavaScript
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,
});

// This configuration will map addresses in line with Magic's 'mainnet' setup.

Common Methods

NoteAll Web.js examples are using [email protected] or later version.

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.BrowserProvider(magic.rpcProvider);

// ⭐️ After user is successfully authenticated

const signer = await provider.getSigner();

const destination = '0xE0cef4417a772512E6C95cEf366403839b0D6D6D';
const amount = ethers.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();

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.BrowserProvider(magic.rpcProvider);

// ⭐️ After user is successfully authenticated

const signer = await 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.BrowserProvider(magic.rpcProvider);

// ⭐️ After user is successfully authenticated

const signer = await provider.getSigner();

// 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.BrowserProvider(magic.rpcProvider);

// ⭐️ After user is successfully authenticated

const signer = await provider.getSigner();

// 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.BrowserProvider(magic.rpcProvider);

// ⭐️ After user is successfully authenticated

const signer = await provider.getSigner();

// 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);

Get Balance

Ethers.js

import { Magic } from 'magic-sdk';
import { ethers } from 'ethers';

const magic = new Magic('YOUR_PUBLISHABLE_API_KEY')
const provider = new ethers.BrowserProvider(magic.rpcProvider);

// ⭐️ After user is successfully authenticated

const signer = await provider.getSigner();

// Get user's Ethereum public address
const address = await signer.getAddress();

// Get user's balance in ether
const balance = ethers.formatEther(
  await provider.getBalance(address), // Balance is in wei
);

Smart Contract

In this example, we’ll be demonstrating how to use Magic with ethers.js to interact with Solidity smart contracts. The simple Hello World contract allows anyone to read and write a message to it.
Solidity
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;
  }
}

Deploy Contract

Ethers.js

import { Magic } from 'magic-sdk';
import { ethers } from 'ethers';

const magic = new Magic('YOUR_PUBLISHABLE_API_KEY');
const provider = new ethers.BrowserProvider(magic.rpcProvider);

// ⭐️ After user is successfully authenticated

const signer = await 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 = contract.deploymentTransaction()

Read From Contract

Ethers.js

import { Magic } from 'magic-sdk';
import { ethers } from 'ethers';

const magic = new Magic('YOUR_PUBLISHABLE_API_KEY');
const provider = new ethers.BrowserProvider(magic.rpcProvider);

// ⭐️ After user is successfully authenticated

const signer = await 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 = 'CONTRACT_ADDRESS';
const contract = new ethers.Contract(contractAddress, contractABI, signer);

// Read message from smart contract
const message = await contract.message();

Write to Contract

Ethers.js

import { Magic } from 'magic-sdk';
import { ethers } from 'ethers';

const magic = new Magic('YOUR_PUBLISHABLE_API_KEY');
const provider = new ethers.BrowserProvider(magic.rpcProvider);

// ⭐️ After user is successfully authenticated

const signer = await 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 = 'CONTRACT_ADDRESS';
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();

Resources