How to use Magic with Ethereum and Arbitrum

Magic Staff ยท July 30, 2021


Note: this guide uses web3.js, but to see a demo with ethers.js click here.


#What is Arbitrum?

Arbitrum is a Layer 2 scaling solution for Ethereum, which launched in May 2021. It uses "optimistic rollups" technology where transactions are submitted directly to the L2, "rolled up" into a single proof, then sent to the layer one chain (Ethereum) to be verified. With smart contract computations being done on L2 rather than L1, it allows for significantly faster and cheaper transactions. Arbitrum is also interoperable with Ethereum and the Ethereum Virtual Machine (EVM) so smart contracts can easily be deployed on Arbitrum without much/any refactoring. With Magic, developers can connect to the Arbitrum network by simply specifying the network URL when initiating a Magic instance. This guide will show how you can create a web3-enabled app, allow users to switch between the Ethereum and Arbitrum networks, call smart contracts, and send transactions.

#Connecting to Arbitrum

In magic.js, simply initialize the Magic instance with the network pointed to your Arbitrum rpc url.

import { Magic } from "magic-sdk";

const customNodeOptions = {
  rpcUrl: "",
  chainId: 421613

export const magic = new Magic("YOUR_API_KEY", {
  network: customNodeOptions

#Viewing User Balance

You can use the native getBalance function of the web3.js library to pull the user's balance for whichever network you iniated Magic with.

const fetchBalance = (address) => {
  web3.eth.getBalance(address).then(bal => setBalance(web3.utils.fromWei(bal)))

return (
  <div className="info">
    {balance.toString().substring(0, 6)} ETH

#Send Transaction

Sending a transaction is also very simple using web3.js.

const sendTransaction = async () => {
    const { transactionHash } = await web3.eth.sendTransaction({
      from: publicAddress,
      to: toAddress,
      value: web3.utils.toWei(amount)

return (
 <div className="container">
  <h1>Send Transaction</h1>
    onChange={(e) => setToAddress(} 
    placeholder="To Address" 
    onChange={(e) => setAmount(} 
  <button onClick={sendTransaction}>Send Transaction</button>

#Calling Smart Contracts

const contractAddress = "0x8e37B2da4D634bE57667326dEBe0c52798753CEf";
  const contract = new web3.eth.Contract(abi, contractAddress);
  const [number, setNumber] = useState();
  const [newNumber, setNewNumber] = useState("");

  const fetchContractNumber = () => {

  useEffect(() => {
  }, []);

  const updateContractNumber = async () => {
    const { transactionHash } = await{
      from: publicAddress

  return (
    <div className="container">
      <h1>Number stored in contract</h1>
      <div className="info">{number}</div>

      <h1>Update Number</h1>
        onChange={(e) => setNewNumber(}
        placeholder="New number"
      <button disabled={disabled} onClick={updateContractNumber}>


That's all there is to it! You've now got an app that allows users to create a wallet with just their email, and connect to the Arbitrum L2 and Ethereum networks within your app.

Let's make some magic!

Did you find what you were looking for?