Frontend Integration

This guide demonstrates how to connect your web application to smart contracts deployed on the Ettios blockchain using popular JavaScript libraries.

Prerequisites

Before you begin, ensure you have:

  • A React, Vue, or similar frontend framework project set up
  • A smart contract deployed on Ettios (see our contract deployment guide)
  • Basic knowledge of JavaScript/TypeScript and frontend development

Choosing a Web3 Library

Several JavaScript libraries can help you interact with the Ettios blockchain. Here are the most popular options:

ethers.js

A complete, compact, and portable Ethereum library for interacting with the Ethereum Blockchain and its ecosystem.

npm install ethers
Documentation

wagmi

A set of React Hooks for working with Ethereum. Built on top of ethers.js, great for React applications.

npm install wagmi viem
Documentation

viem

A lightweight TypeScript interface for Ethereum, with a focus on reliability, efficiency, and excellent developer experience.

npm install viem
Documentation

Integrating with ethers.js

Here's how to connect to the Ettios network and interact with a smart contract using ethers.js:

1. Connect to Ettios

import { ethers } from 'ethers';

// Connect to Ettios using a provider
const provider = new ethers.providers.JsonRpcProvider("https://rpc.ettiosblockchain.io");

// Or connect via MetaMask if available in the browser
async function connectToMetaMask() {
  if (window.ethereum) {
    try {
      // Request account access
      await window.ethereum.request({ method: 'eth_requestAccounts' });
      return new ethers.providers.Web3Provider(window.ethereum);
    } catch (error) {
      console.error("User denied account access");
    }
  } else {
    console.error("MetaMask is not installed");
  }
}

2. Load a Contract

// Contract ABI (Application Binary Interface)
const abi = [
  "function greet() view returns (string)",
  "function setGreeting(string _greeting)"
];

// Contract address (replace with your deployed contract address)
const contractAddress = "0x1234567890123456789012345678901234567890";

// Create a contract instance
const contract = new ethers.Contract(contractAddress, abi, provider);

// If you want to make state-changing calls, connect with a signer
async function getContractWithSigner() {
  const metaMaskProvider = await connectToMetaMask();
  const signer = metaMaskProvider.getSigner();
  return new ethers.Contract(contractAddress, abi, signer);
}

3. Read Contract Data

// Read data from the contract (view functions)
async function readGreeting() {
  try {
    const greeting = await contract.greet();
    console.log("Current greeting:", greeting);
    return greeting;
  } catch (error) {
    console.error("Error reading greeting:", error);
  }
}

4. Write to the Contract

// Write data to the contract (state-changing functions)
async function setNewGreeting(newGreeting) {
  try {
    const contractWithSigner = await getContractWithSigner();
    const tx = await contractWithSigner.setGreeting(newGreeting);
    
    // Wait for the transaction to be mined
    console.log("Transaction sent, waiting for confirmation...");
    const receipt = await tx.wait();
    console.log("Transaction confirmed:", receipt);
    return receipt;
  } catch (error) {
    console.error("Error setting greeting:", error);
  }
}

Implementing with wagmi (React)

If you're using React, wagmi provides a more declarative way to interact with Ethereum. Here's how to set up and use it with Ettios:

1. Configure wagmi

// src/wagmi.ts
import { configureChains, createConfig } from 'wagmi'
import { mainnet, sepolia } from 'wagmi/chains'
import { publicProvider } from 'wagmi/providers/public'
import { MetaMaskConnector } from 'wagmi/connectors/metaMask'

// Define the Ettios chain
const ettios = {
  id: 2237,
  name: 'Ettios',
  network: 'ettios',
  nativeCurrency: {
    name: 'ETTIA',
    symbol: 'ETTIA',
    decimals: 18,
  },
  rpcUrls: {
    default: {
      http: ['https://rpc.ettiosblockchain.io'],
    },
    public: {
      http: ['https://rpc.ettiosblockchain.io'],
    },
  },
  blockExplorers: {
    default: {
      name: 'EttiosScan',
      url: 'https://scan.ettiosblockchain.io',
    },
  },
}

// Configure chains & providers
const { chains, publicClient } = configureChains(
  [ettios, mainnet, sepolia],
  [publicProvider()]
)

// Set up wagmi config
export const config = createConfig({
  autoConnect: true,
  connectors: [
    new MetaMaskConnector({ chains }),
  ],
  publicClient,
})

export { chains }

2. Wrap your app with WagmiConfig

// src/App.tsx or _app.tsx
import { WagmiConfig } from 'wagmi'
import { config } from './wagmi'

function App() {
  return (
    <WagmiConfig config={config}>
      {/* Your app components */}
    </WagmiConfig>
  )
}

3. Use wagmi hooks to interact with contracts

// ContractInteraction.tsx
import { useContractRead, useContractWrite, useAccount, useConnect, useDisconnect } from 'wagmi'
import { MetaMaskConnector } from 'wagmi/connectors/metaMask'

function ContractInteraction() {
  // Contract configuration
  const contractConfig = {
    address: '0x1234567890123456789012345678901234567890',
    abi: [
      "function greet() view returns (string)",
      "function setGreeting(string _greeting)"
    ],
  }

  // Connection state
  const { address, isConnected } = useAccount()
  const { connect } = useConnect({
    connector: new MetaMaskConnector(),
  })
  const { disconnect } = useDisconnect()

  // Read from contract
  const { data: greeting, isLoading: isLoadingGreeting } = useContractRead({
    ...contractConfig,
    functionName: 'greet',
  })

  // Write to contract
  const { write: setGreeting, isLoading: isWriting } = useContractWrite({
    ...contractConfig,
    functionName: 'setGreeting',
  })

  // Connect wallet button
  if (!isConnected) {
    return <button onClick={() => connect()}>Connect Wallet</button>
  }

  return (
    <div>
      <div>Connected to {address}</div>
      <button onClick={() => disconnect()}>Disconnect</button>
      
      <div>
        <h3>Current Greeting</h3>
        {isLoadingGreeting ? 'Loading...' : greeting}
      </div>
      
      <div>
        <h3>Update Greeting</h3>
        <input
          id="greeting"
          placeholder="New greeting"
          onChange={(e) => setNewGreeting(e.target.value)}
        />
        <button
          onClick={() => setGreeting({ args: [newGreeting] })}
          disabled={isWriting}
        >
          {isWriting ? 'Updating...' : 'Update'}
        </button>
      </div>
    </div>
  )
}

Handling Network Switching

It's important to handle cases where users need to switch to the Ettios network. Here's how to implement network switching:

async function switchToEttios() {
  if (!window.ethereum) {
    alert("Please install MetaMask to use this feature");
    return;
  }

  try {
    // Try to switch to the Ettios network
    await window.ethereum.request({
      method: 'wallet_switchEthereumChain',
      params: [{ chainId: '0x8bd' }], // Hexadecimal chain ID
    });
  } catch (switchError) {
    // This error code indicates that the chain has not been added to MetaMask
    if (switchError.code === 4902) {
      try {
        await window.ethereum.request({
          method: 'wallet_addEthereumChain',
          params: [
            {
              chainId: '0x8bd',
              chainName: 'Ettios',
              nativeCurrency: {
                name: 'ETTIA',
                symbol: 'ETTIA',
                decimals: 18,
              },
              rpcUrls: ['https://rpc.ettiosblockchain.io'],
              blockExplorerUrls: ['https://scan.ettiosblockchain.io'],
            },
          ],
        });
      } catch (addError) {
        console.error("Error adding Ettios network:", addError);
      }
    } else {
      console.error("Error switching to Ettios network:", switchError);
    }
  }
}

Best Practices

Error Handling

Always implement proper error handling to provide feedback to users:

  • Catch and display transaction errors
  • Handle network connection issues
  • Show user-friendly error messages
  • Add loading states during transactions

Gas Optimization

Consider gas costs, especially for complex transactions:

  • Estimate gas before sending transactions
  • Allow users to adjust gas settings for important operations
  • Batch transactions when possible to reduce overall gas costs

Testing

Thoroughly test your dApp across different scenarios:

  • Test on both testnet and mainnet environments
  • Implement end-to-end testing for critical user flows
  • Test with different wallets (MetaMask, WalletConnect, etc.)
  • Verify behavior when network is congested

Security Reminder

Never store private keys or sensitive information in frontend code. Use secure authentication methods and backend services for handling sensitive operations.