Build a Frontend

Build a simple frontend for your deployed contract with Vite and Wagmi

Choose between using testnet or a local node.

Frontend setup

Choose between using React or Vue for your frontend.

  1. Create a Vite React project.
    npm create vite@latest token-frontend -- --template react-ts --no-interactive
    
  2. Move into the project folder and install the required packages.
    cd token-frontend
    
    npm install
    npm install wagmi viem@2.x @tanstack/react-query
    
  3. Create file in the src folder called wagmi.ts and copy/paste the config below.
    import { createConfig, http } from 'wagmi';
    import { injected } from 'wagmi/connectors';
    import { defineChain } from 'viem';
    import { anvil } from 'viem/chains';
    
    const zksyncOSTestnet = defineChain({
      id: 8022833,
      name: 'ZKsync OS Developer Preview',
      nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
      rpcUrls: { default: { http: ['https://zksync-os-testnet-alpha.zksync.dev'] } },
      blockExplorers: {
        default: {
          name: 'ZKsync OS Developer Preview Explorer',
          url: 'https://zksync-os-testnet-alpha.staging-scan-v2.zksync.dev',
        },
      },
    });
    
    export const activeChain = import.meta.env.VITE_CHAIN === 'local' ? anvil : zksyncOSTestnet;
    
    export const config =
      import.meta.env.VITE_CHAIN === 'local'
        ? createConfig({
            chains: [anvil],
            connectors: [injected()],
            transports: {
              [anvil.id]: http(),
            },
          })
        : createConfig({
            chains: [zksyncOSTestnet],
            connectors: [injected()],
            transports: {
              [zksyncOSTestnet.id]: http(),
            },
          });
    
  4. Next, configure the wagmi and query client providers in src/main.tsx.
    import React from 'react';
    import ReactDOM from 'react-dom/client';
    import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
    import { WagmiProvider } from 'wagmi';
    import App from './App';
    import { config } from './wagmi';
    import './index.css';
    
    const queryClient = new QueryClient();
    
    ReactDOM.createRoot(document.getElementById('root')!).render(
      <React.StrictMode>
        <WagmiProvider config={config}>
          <QueryClientProvider client={queryClient}>
            <App />
          </QueryClientProvider>
        </WagmiProvider>
      </React.StrictMode>
    );
    
  5. Replace src/App.tsx with the code below.
  1. Create a .env file in the root of the token-frontend folder and add your deployed contract address as VITE_CONTRACT_ADDRESS.
    VITE_CONTRACT_ADDRESS=0x...
    
  1. Finally you can start the development server.
    npm run dev
    
  1. Create a Vite Vue project.
    npm create vite@latest token-frontend-vue -- --template vue-ts --no-interactive
    
  2. Move into the project folder and install the required packages.
    cd token-frontend-vue
    
    npm install
    npm install @wagmi/vue viem@2.x @tanstack/vue-query
    
  3. Create file in the src folder called wagmi.ts and copy/paste the config below.
    import { createConfig, http, injected } from '@wagmi/vue';
    import { defineChain } from 'viem';
    import { anvil } from 'viem/chains';
    
    const zksyncOSTestnet = defineChain({
      id: 8022833,
      name: 'ZKsync OS Developer Preview',
      nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
      rpcUrls: { default: { http: ['https://zksync-os-testnet-alpha.zksync.dev'] } },
      blockExplorers: {
        default: {
          name: 'ZKsync OS Developer Preview Explorer',
          url: 'https://zksync-os-testnet-alpha.staging-scan-v2.zksync.dev',
        },
      },
    });
    
    export const activeChain = import.meta.env.VITE_CHAIN === 'local' ? anvil : zksyncOSTestnet;
    
    export const config =
      import.meta.env.VITE_CHAIN === 'local'
        ? createConfig({
            chains: [anvil],
            connectors: [injected()],
            transports: {
              [anvil.id]: http(),
            },
          })
        : createConfig({
            chains: [zksyncOSTestnet],
            connectors: [injected()],
            transports: {
              [zksyncOSTestnet.id]: http(),
            },
          });
    
  4. Next, configure the wagmi plugin and query client in src/main.ts.
    import { QueryClient, VueQueryPlugin } from '@tanstack/vue-query';
    import { WagmiPlugin } from '@wagmi/vue';
    import { createApp } from 'vue';
    import App from './App.vue';
    import { config } from './wagmi';
    
    const app = createApp(App);
    const queryClient = new QueryClient();
    
    app.use(VueQueryPlugin, { queryClient });
    app.use(WagmiPlugin, { config });
    
    app.mount('#app');
    
  5. Replace src/App.vue with the code below.
  1. Create a .env file in the root of the token-frontend-vue folder and add your deployed contract address as VITE_CONTRACT_ADDRESS.
    VITE_CONTRACT_ADDRESS=0x...
    
  1. Finally you can start the development server.
    npm run dev
    

Frontend setup

Choose between using React or Vue for your frontend.

  1. Create a Vite React project.
    npm create vite@latest token-frontend -- --template react-ts --no-interactive
    
  2. Move into the project folder and install the required packages.
    cd token-frontend
    
    npm install
    npm install wagmi viem@2.x @tanstack/react-query
    
  3. Create file in the src folder called wagmi.ts and copy/paste the config below.
    import { createConfig, http } from 'wagmi';
    import { injected } from 'wagmi/connectors';
    import { defineChain } from 'viem';
    import { anvil } from 'viem/chains';
    
    const zksyncOSTestnet = defineChain({
      id: 8022833,
      name: 'ZKsync OS Developer Preview',
      nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
      rpcUrls: { default: { http: ['https://zksync-os-testnet-alpha.zksync.dev'] } },
      blockExplorers: {
        default: {
          name: 'ZKsync OS Developer Preview Explorer',
          url: 'https://zksync-os-testnet-alpha.staging-scan-v2.zksync.dev',
        },
      },
    });
    
    export const activeChain = import.meta.env.VITE_CHAIN === 'local' ? anvil : zksyncOSTestnet;
    
    export const config =
      import.meta.env.VITE_CHAIN === 'local'
        ? createConfig({
            chains: [anvil],
            connectors: [injected()],
            transports: {
              [anvil.id]: http(),
            },
          })
        : createConfig({
            chains: [zksyncOSTestnet],
            connectors: [injected()],
            transports: {
              [zksyncOSTestnet.id]: http(),
            },
          });
    
  4. Next, configure the wagmi and query client providers in src/main.tsx.
    import React from 'react';
    import ReactDOM from 'react-dom/client';
    import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
    import { WagmiProvider } from 'wagmi';
    import App from './App';
    import { config } from './wagmi';
    import './index.css';
    
    const queryClient = new QueryClient();
    
    ReactDOM.createRoot(document.getElementById('root')!).render(
      <React.StrictMode>
        <WagmiProvider config={config}>
          <QueryClientProvider client={queryClient}>
            <App />
          </QueryClientProvider>
        </WagmiProvider>
      </React.StrictMode>
    );
    
  5. Replace src/App.tsx with the code below.
  1. Create a .env file in the root of the token-frontend folder, add your deployed contract address as VITE_CONTRACT_ADDRESS, and set VITE_CHAIN to local.
    VITE_CONTRACT_ADDRESS=0x...
    VITE_CHAIN=local
    
  1. Finally you can start the development server.
    npm run dev
    
  1. Add your local node to your browser wallet. Depending on what browser wallet you are using, the steps for this may be different.
    For Metamask, click on the top right menu bars, select "Networks", and then click on "Add a Custom Network". Enter the name "Anvil", http://localhost:8545 as the RPC URL, 31337 for the chain ID, and ETH as the currency symbol.
  2. Next, either import one of the rich wallets from anvil to your browser wallet using one of the private keys logged when starting the node, or use the command below to send some test ETH to your wallet. The cast CLI should already be installed through foundryup.
    cast send <0x_YOUR_WALLET_ADDRESS> --value 1ether --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 --rpc-url http://localhost:8545
    

    You can use the interact script in the previous step to send some tokens to your address if you need.
  1. Create a Vite Vue project.
    npm create vite@latest token-frontend-vue -- --template vue-ts --no-interactive
    
  2. Move into the project folder and install the required packages.
    cd token-frontend-vue
    
    npm install
    npm install @wagmi/vue viem@2.x @tanstack/vue-query
    
  3. Create file in the src folder called wagmi.ts and copy/paste the config below.
    import { createConfig, http, injected } from '@wagmi/vue';
    import { defineChain } from 'viem';
    import { anvil } from 'viem/chains';
    
    const zksyncOSTestnet = defineChain({
      id: 8022833,
      name: 'ZKsync OS Developer Preview',
      nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
      rpcUrls: { default: { http: ['https://zksync-os-testnet-alpha.zksync.dev'] } },
      blockExplorers: {
        default: {
          name: 'ZKsync OS Developer Preview Explorer',
          url: 'https://zksync-os-testnet-alpha.staging-scan-v2.zksync.dev',
        },
      },
    });
    
    export const activeChain = import.meta.env.VITE_CHAIN === 'local' ? anvil : zksyncOSTestnet;
    
    export const config =
      import.meta.env.VITE_CHAIN === 'local'
        ? createConfig({
            chains: [anvil],
            connectors: [injected()],
            transports: {
              [anvil.id]: http(),
            },
          })
        : createConfig({
            chains: [zksyncOSTestnet],
            connectors: [injected()],
            transports: {
              [zksyncOSTestnet.id]: http(),
            },
          });
    
  4. Next, configure the wagmi plugin and query client in src/main.ts.
    import { QueryClient, VueQueryPlugin } from '@tanstack/vue-query';
    import { WagmiPlugin } from '@wagmi/vue';
    import { createApp } from 'vue';
    import App from './App.vue';
    import { config } from './wagmi';
    
    const app = createApp(App);
    const queryClient = new QueryClient();
    
    app.use(VueQueryPlugin, { queryClient });
    app.use(WagmiPlugin, { config });
    
    app.mount('#app');
    
  5. Replace src/App.vue with the code below.
  1. Create a .env file in the root of the token-frontend-vue folder, add your deployed contract address as VITE_CONTRACT_ADDRESS, and set VITE_CHAIN to local.
    VITE_CONTRACT_ADDRESS=0x...
    VITE_CHAIN=local
    
  1. Finally you can start the development server.
    npm run dev
    
  1. Add your local node to your browser wallet. Depending on what browser wallet you are using, the steps for this may be different.
    For Metamask, click on the top right menu bars, select "Networks", and then click on "Add a Custom Network". Enter the name "Anvil", http://localhost:8545 as the RPC URL, 31337 for the chain ID, and ETH as the currency symbol.
  2. Next, either import one of the rich wallets from anvil to your browser wallet using one of the private keys logged when starting the node, or use the command below to send some test ETH to your wallet. The cast CLI should already be installed through foundryup.
    cast send <0x_YOUR_WALLET_ADDRESS> --value 1ether --private-key 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 --rpc-url http://localhost:8545
    

    You can use the interact script in the previous step to send some tokens to your address if you need.

Testing the frontend

Now you can test the frontend by opening http://localhost:5173/ in your browser, connecting your wallet, checking the token metadata, and submitting a token transfer.

Takeaways

  • ZKsync chains after the Atlas upgrade are fully EVM-equivalent, meaning you can write smart contracts in Solidity or Vyper as in Ethereum and test apps with standard EVM tooling.
  • You can use ZKsync's latest testnet, the ZKsync OS Developer Preview, to test your apps as you develop them.
  • As you continue building with ZKsync, make sure to join our GitHub Discussions Community to ask questions, get help and help other devs building on ZKsync, or share your project.

Made with ❤️ by the ZKsync Community