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 etherswagmi
A set of React Hooks for working with Ethereum. Built on top of ethers.js, great for React applications.
npm install wagmi viemviem
A lightweight TypeScript interface for Ethereum, with a focus on reliability, efficiency, and excellent developer experience.
npm install viemIntegrating 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.
Next Steps
Ready to expand your dApp's capabilities?