Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.teqoin.io/llms.txt

Use this file to discover all available pages before exploring further.

dApp Integration Guide

Learn how to integrate TeQoin L2 into your web application and enable users to interact with your smart contracts.
What You’ll Learn:
  • Connect wallets (MetaMask, WalletConnect)
  • Interact with smart contracts
  • Handle transactions
  • Listen to events
  • Best practices for production dApps

🎯 Integration Stack

Ethers.js v6

RecommendedModern, lightweight library

Web3.js

ClassicOriginal Ethereum library

Wagmi + Viem

React HooksModern React integration

🚀 Quick Start Template

A minimal dApp to get you started quickly.

Complete Working Example

<!DOCTYPE html>
<html>
<head>
    <title>TeQoin dApp</title>
    <script src="https://cdn.ethers.io/lib/ethers-5.7.umd.min.js"></script>
</head>
<body>
    <h1>TeQoin dApp Example</h1>
    
    <!-- Connect Wallet -->
    <button id="connectBtn">Connect Wallet</button>
    <p>Connected: <span id="account">Not connected</span></p>
    <p>Network: <span id="network">Unknown</span></p>
    
    <!-- Contract Interaction -->
    <h2>Contract Interaction</h2>
    <input id="addressInput" placeholder="Contract Address" />
    <button id="getBalanceBtn">Get Balance</button>
    <p>Balance: <span id="balance">-</span></p>
    
    <script src="app.js"></script>
</body>
</html>

Modern, lightweight library for Ethereum interaction.

Installation

# Install ethers.js v6
npm install ethers

# Or use CDN
<script src="https://cdn.ethers.io/lib/ethers-5.7.umd.min.js"></script>

Connect to TeQoin

import { ethers } from 'ethers';

// Connect to TeQoin L2
const provider = new ethers.JsonRpcProvider('https://rpc.teqoin.io');

// Check connection
const network = await provider.getNetwork();
console.log('Connected to chain ID:', network.chainId); // 420377n

// Get latest block
const blockNumber = await provider.getBlockNumber();
console.log('Latest block:', blockNumber);

Interact with Smart Contracts

import { ethers } from 'ethers';

// Contract ABI (only the functions you need)
const abi = [
    "function totalSupply() view returns (uint256)",
    "function balanceOf(address) view returns (uint256)",
    "function name() view returns (string)",
    "function symbol() view returns (string)"
];

// Connect to contract
const provider = new ethers.JsonRpcProvider('https://rpc.teqoin.io');
const contract = new ethers.Contract(
    '0x5E3A9432a2D6eb0c5D362A0A2F58Bc02Db45850D', // Contract address
    abi,
    provider
);

// Call view functions (no gas cost)
const totalSupply = await contract.totalSupply();
const balance = await contract.balanceOf('0x...');
const name = await contract.name();

console.log('Total Supply:', ethers.formatUnits(totalSupply, 18));
console.log('Balance:', ethers.formatUnits(balance, 18));
console.log('Name:', name);

🔷 Web3.js Integration

Classic Ethereum library, still widely used.

Installation

npm install web3

Basic Usage

const Web3 = require('web3');

// Connect to TeQoin L2
const web3 = new Web3('https://rpc.teqoin.io');

// Check connection
const chainId = await web3.eth.getChainId();
console.log('Chain ID:', chainId); // 420377

// Get latest block
const blockNumber = await web3.eth.getBlockNumber();
console.log('Latest block:', blockNumber);

⚛️ Wagmi + Viem Integration (React)

Modern React hooks for Ethereum.

Installation

npm install wagmi viem @tanstack/react-query

Setup

import { http, createConfig } from 'wagmi';
import { teqoin } from './chains';

export const config = createConfig({
  chains: [teqoin],
  transports: {
    [teqoin.id]: http('https://rpc.teqoin.io'),
  },
});

React Components

import { useAccount, useConnect, useDisconnect } from 'wagmi';
import { injected } from 'wagmi/connectors';

export function ConnectButton() {
  const { address, isConnected } = useAccount();
  const { connect } = useConnect();
  const { disconnect } = useDisconnect();

  if (isConnected) {
    return (
      <div>
        <p>Connected: {address}</p>
        <button onClick={() => disconnect()}>Disconnect</button>
      </div>
    );
  }

  return (
    <button onClick={() => connect({ connector: injected() })}>
      Connect Wallet
    </button>
  );
}

🎨 Complete React dApp Example

A production-ready React + Wagmi dApp template:
import { useState } from 'react';
import { useAccount, useConnect, useDisconnect, useReadContract, useWriteContract } from 'wagmi';
import { injected } from 'wagmi/connectors';
import { parseEther, formatEther } from 'viem';

const CONTRACT_ADDRESS = '0x5E3A9432a2D6eb0c5D362A0A2F58Bc02Db45850D';
const CONTRACT_ABI = [
  {
    name: 'balanceOf',
    type: 'function',
    stateMutability: 'view',
    inputs: [{ name: 'account', type: 'address' }],
    outputs: [{ type: 'uint256' }],
  },
  {
    name: 'transfer',
    type: 'function',
    stateMutability: 'nonpayable',
    inputs: [
      { name: 'to', type: 'address' },
      { name: 'amount', type: 'uint256' },
    ],
    outputs: [{ type: 'bool' }],
  },
];

function App() {
  const { address, isConnected } = useAccount();
  const { connect } = useConnect();
  const { disconnect } = useDisconnect();
  const [recipient, setRecipient] = useState('');
  const [amount, setAmount] = useState('');

  // Read balance
  const { data: balance } = useReadContract({
    address: CONTRACT_ADDRESS,
    abi: CONTRACT_ABI,
    functionName: 'balanceOf',
    args: address ? [address] : undefined,
  });

  // Write transaction
  const { writeContract, isPending } = useWriteContract();

  const handleTransfer = () => {
    if (!recipient || !amount) return;
    
    writeContract({
      address: CONTRACT_ADDRESS,
      abi: CONTRACT_ABI,
      functionName: 'transfer',
      args: [recipient, parseEther(amount)],
    });
  };

  return (
    <div style={{ padding: '20px' }}>
      <h1>TeQoin dApp</h1>
      
      {/* Connect Wallet */}
      {!isConnected ? (
        <button onClick={() => connect({ connector: injected() })}>
          Connect Wallet
        </button>
      ) : (
        <div>
          <p>Connected: {address}</p>
          <p>Balance: {balance ? formatEther(balance) : '0'} MTK</p>
          <button onClick={() => disconnect()}>Disconnect</button>
          
          {/* Transfer Form */}
          <div style={{ marginTop: '20px' }}>
            <h2>Transfer Tokens</h2>
            <input
              placeholder="Recipient Address"
              value={recipient}
              onChange={(e) => setRecipient(e.target.value)}
              style={{ width: '100%', marginBottom: '10px' }}
            />
            <input
              placeholder="Amount"
              value={amount}
              onChange={(e) => setAmount(e.target.value)}
              style={{ width: '100%', marginBottom: '10px' }}
            />
            <button onClick={handleTransfer} disabled={isPending}>
              {isPending ? 'Sending...' : 'Transfer'}
            </button>
          </div>
        </div>
      )}
    </div>
  );
}

export default App;

🔐 Best Practices

Security

    // ❌ BAD: No validation
    const tx = await contract.transfer(userInput, amount);
    
    // ✅ GOOD: Validate addresses
    import { ethers } from 'ethers';
    
    if (!ethers.isAddress(userInput)) {
      throw new Error('Invalid address');
    }
    
    const tx = await contract.transfer(userInput, amount);
    try {
      const tx = await contract.transfer(to, amount);
      await tx.wait();
      alert('Transfer successful!');
    } catch (error) {
      if (error.code === 'ACTION_REJECTED') {
        alert('Transaction cancelled');
      } else if (error.code === 'INSUFFICIENT_FUNDS') {
        alert('Insufficient balance');
      } else {
        alert('Transaction failed: ' + error.message);
      }
    }
    const provider = new ethers.BrowserProvider(window.ethereum);
    const network = await provider.getNetwork();
    
    if (network.chainId !== 420377n) {
      alert('Please switch to TeQoin L2');
      await switchToTeQoin();
    }

Performance

Use Read-Only Provider for View Functions
// ❌ BAD: Using wallet provider for reads (slower)
const provider = new ethers.BrowserProvider(window.ethereum);

// ✅ GOOD: Use direct RPC for reads (faster)
const readProvider = new ethers.JsonRpcProvider('https://rpc.teqoin.io');
const contract = new ethers.Contract(address, abi, readProvider);
Cache Contract Instances
// ❌ BAD: Creating new instance every time
function getBalance() {
  const contract = new ethers.Contract(...);
  return contract.balanceOf(address);
}

// ✅ GOOD: Reuse contract instance
const contract = new ethers.Contract(...);
function getBalance() {
  return contract.balanceOf(address);
}

📱 Mobile Wallet Integration

WalletConnect Support

npm install @walletconnect/web3-provider
import WalletConnectProvider from '@walletconnect/web3-provider';
import { ethers } from 'ethers';

const walletConnectProvider = new WalletConnectProvider({
  rpc: {
    420377: 'https://rpc.teqoin.io',
  },
  chainId: 420377,
});

// Enable session
await walletConnectProvider.enable();

// Create ethers provider
const provider = new ethers.providers.Web3Provider(walletConnectProvider);
const signer = provider.getSigner();

🎯 Testing Your dApp

Local Testing

# Use Hardhat local node
npx hardhat node --fork https://rpc.teqoin.io

# Your dApp can connect to:
# http://localhost:8545

Testnet Testing

// Configure for testnet
const provider = new ethers.JsonRpcProvider('https://rpc-testnet.teqoin.io');

📚 Additional Resources

Ethers.js Docs

Official Ethers.js documentation

Wagmi Docs

React hooks for Ethereum

Web3.js Docs

Web3.js documentation

Network Info

TeQoin network details

🎯 Next Steps

Deploy Your dApp

Host on Vercel, Netlify, or IPFS

Add Analytics

Track user interactions

Build Backend

Add off-chain components

Get Users

Market your dApp

🎉 Developer Documentation Complete!

You’ve completed all developer guides:
  • ✅ Network Information
  • ✅ Smart Contracts
  • ✅ Deploy Contract
  • ✅ Verify Contract
  • ✅ Integration Guide
Ready to build amazing dApps on TeQoin L2! 🚀