Deploy & Interact with a KYC DApp
Students will compile, deploy, and interact with a KYC smart contract, then build a tiny front‑end using Web3.
Instructional Videos
- 🎥 Video 1: Smart Contract (KYC.sol)
- 🎥 Video 2: Truffle Console (optional)
- 🎥 Video 3: Web3 Front‑End (part 1)
- 🎥 Video 4: Web3 Front‑End (part 2)
(Instructor: paste links here.)
1) Set Up Your Environment
- Install Node.js (LTS) → verify:
node -v npm -v
- Install Truffle (global) → verify:
npm install -g truffle truffle version
- Install Ganache (GUI or CLI) and start a fresh workspace (RPC http://127.0.0.1:7545).
2) Initialize a Truffle Project
mkdir my-project
cd my-project
truffle initSet truffle-config.js for Ganache and Solidity 0.8.x:
module.exports = {
  networks: {
    development: { host: "127.0.0.1", port: 7545, network_id: "*" },
  },
  compilers: { solc: { version: "0.8.20" } }
};3) Write Your KYC Smart Contract
Create contracts/KYC.sol and paste:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract KYC {
    struct Bank { string name; address bankAddress; }
    struct Customer { string name; address customerAddress; bool isVerified; }
    mapping(address => Bank) public banks;
    mapping(address => Customer) public customers;
    address[] public bankList;
    address[] public customerList;
    event BankAdded(string name, address bankAddress);
    event CustomerAdded(string name, address customerAddress);
    event CustomerVerified(address customerAddress);
    function addNewBank(string memory name, address bankAddress) public {
        require(bankAddress != address(0), "Invalid address");
        require(bytes(name).length > 0, "Bank name required");
        banks[bankAddress] = Bank(name, bankAddress);
        bankList.push(bankAddress);
        emit BankAdded(name, bankAddress);
    }
    function addNewCustomer(string memory name, address customerAddress) public {
        require(customerAddress != address(0), "Invalid address");
        require(bytes(name).length > 0, "Customer name required");
        customers[customerAddress] = Customer(name, customerAddress, false);
        customerList.push(customerAddress);
        emit CustomerAdded(name, customerAddress);
    }
    function verifyCustomer(address customerAddress) public {
        require(customerAddress != address(0), "Invalid address");
        require(customers[customerAddress].customerAddress != address(0), "Customer missing");
        customers[customerAddress].isVerified = true;
        emit CustomerVerified(customerAddress);
    }
    function getBanks() public view returns (Bank[] memory) {
        Bank[] memory allBanks = new Bank[](bankList.length);
        for (uint i = 0; i < bankList.length; i++) {
            allBanks[i] = banks[bankList[i]];
        }
        return allBanks;
    }
    function getCustomers() public view returns (Customer[] memory) {
        Customer[] memory allCustomers = new Customer[](customerList.length);
        for (uint i = 0; i < customerList.length; i++) {
            allCustomers[i] = customers[customerList[i]];
        }
        return allCustomers;
    }
}
Compile:
truffle compile4) Migration Script & Deploy
Create migrations/2_deploy_contracts.js:
const KYC = artifacts.require("KYC");
module.exports = function(deployer){ deployer.deploy(KYC); };
Start Ganache, then deploy:
truffle migrate --network developmentbuild/contracts/KYC.json.5) Interact via Truffle Console (optional but helpful)
truffle console --network development
const KYC = artifacts.require("KYC");
const kyc = await KYC.deployed();
const accounts = await web3.eth.getAccounts();
// Add banks
await kyc.addNewBank("Bank1", accounts[1]);
await kyc.addNewBank("Bank2", accounts[2]);
// Add customers
await kyc.addNewCustomer("Customer1", accounts[3]);
await kyc.addNewCustomer("Customer2", accounts[4]);
// Verify
await kyc.verifyCustomer(accounts[3]);
// Read back
const banks = await kyc.getBanks();
const customers = await kyc.getCustomers();
console.log(banks);
console.log(customers);
6) Minimal Front‑End (Vanilla Web3, no React)
We’ll serve a simple HTML page with lite-server and auto‑load ABI + address from Truffle’s build JSON.
6.1 Create front‑end folder & install tools
mkdir frontend
cd frontend
npm init -y
npm install web3 lite-server --save-dev6.2 Add package.json script
{
  "name": "kyc-dapp",
  "version": "1.0.0",
  "private": true,
  "scripts": { "start": "lite-server" },
  "devDependencies": { "lite-server": "^2.6.1" },
  "dependencies": { "web3": "^1.10.4" }
}
6.3 Add bs-config.json (so the browser can fetch ../build/)
{ "server": { "baseDir": ["./", "../"] } }
6.4 index.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <title>KYC DApp</title>
  <style> body{font-family:Arial,sans-serif;background:#f4f4f4;padding:20px} .card{max-width:720px;margin:auto;background:#fff;padding:20px;border-radius:10px;box-shadow:0 0 10px rgba(0,0,0,.1)} input,button{padding:10px;margin:6px 0;border-radius:6px;border:1px solid #ccc} button{background:#2563eb;color:#fff;border:none;cursor:pointer} button:hover{opacity:.9} table{width:100%;border-collapse:collapse;margin-top:10px} td,th{border-bottom:1px solid #e5e7eb;padding:8px;text-align:left} .muted{color:#6b7280} </style>
</head>
<body>
  <div class="card">
    <h1>KYC DApp</h1>
    <button id="connect">Connect MetaMask</button>
    <div id="who" class="muted"></div>
    <h2>Add New Bank</h2>
    <input id="bankName" placeholder="Bank Name"/>
    <input id="bankAddr" placeholder="Bank Address 0x..."/>
    <button id="addBank">Add Bank</button>
    <h2>Add New Customer</h2>
    <input id="custName" placeholder="Customer Name"/>
    <input id="custAddr" placeholder="Customer Address 0x..."/>
    <button id="addCust">Add Customer</button>
    <h2>Verify Customer</h2>
    <input id="verifyAddr" placeholder="Customer Address 0x..."/>
    <button id="verifyBtn">Verify</button>
    <p id="status" class="muted"></p>
    <h3>Banks</h3>
    <table id="banksTbl"><thead><tr><th>Name</th><th>Address</th></tr></thead><tbody></tbody></table>
    <h3>Customers</h3>
    <table id="custTbl"><thead><tr><th>Name</th><th>Address</th><th>Verified</th></tr></thead><tbody></tbody></table>
  </div>
  <script src="https://cdn.jsdelivr.net/npm/web3@1.10.4/dist/web3.min.js"></script>
  <script src="app.js"></script>
</body>
</html>
6.5 app.js
let web3, accounts, kyc;
const ABI_URL = '../build/contracts/KYC.json';
const el = id => document.getElementById(id);
const setStatus = m => el('status').textContent = m;
async function connect(){
  if(!window.ethereum){ alert('Please install MetaMask'); return; }
  web3 = new Web3(window.ethereum);
  accounts = await window.ethereum.request({ method: 'eth_requestAccounts' });
  el('who').textContent = `Connected as ${accounts[0]}`;
  await loadContract();
}
async function loadContract(){
  const res = await fetch(ABI_URL); const json = await res.json();
  const abi = json.abi;
  let addr = '';
  const nets = json.networks || {}; const ids = Object.keys(nets);
  if(ids.length){ addr = nets[ids[ids.length-1]].address; }
  if(!addr){ setStatus('❗ Set contract address in app.js or redeploy.'); return; }
  kyc = new web3.eth.Contract(abi, addr);
  setStatus('Contract loaded: ' + addr);
  await refreshTables();
}
async function refreshTables(){
  const banks = await kyc.methods.getBanks().call();
  const custs = await kyc.methods.getCustomers().call();
  el('banksTbl').querySelector('tbody').innerHTML = banks.map(b=>`${b.name} ${b.bankAddress} ${c.name} ${c.customerAddress} ${c.isVerified} Prefer React instead?
Use Create React App and port the same three calls (addNewBank, addNewCustomer, verifyCustomer) into event handlers. If you see a Babel warning, add @babel/plugin-proposal-private-property-in-object as a dev dependency.
7) Run & Test
- Start Ganache (GUI quickstart, RPC 7545).
- In my-projectdeploy the contract:truffle migrate --network development.
- In my-project/frontend:npm start→ openhttp://localhost:3000.
- MetaMask → switch to the Ganache network (host 127.0.0.1, port7545, chain ID 1337/5777).
- Connect, add a bank, add a customer, verify customer → watch updates in the tables.
Troubleshooting (Quick Fixes)
- Wrong address/ABI: Ensure the front‑end fetches ../build/contracts/KYC.jsonand that you redeployed after edits.
- MetaMask on wrong network: Switch to your Ganache RPC; import a Ganache account if you want to act as sender.
- Port 3000 busy: stop other dev servers or configure lite-serverto another port.
- Ganache reset: Restart the workspace if transactions look stuck; in MetaMask you can also reset nonce (dev only).
- Gas errors: Use estimateGasas shown; ensure sender has ETH (Ganache prefunds accounts).
Advanced Version (Admin + Permissions)
The appendix in your spec mentions an admin (kycadmin) and bank permissions (canAddCustomers/canPerformKYC). That’s a stricter model. For class, start with the beginner contract above. As extra credit, evolve it by adding an owner, modifiers, and permission bits on the Bank struct, then gate the functions accordingly.
Submission Checklist
- Screenshot: Ganache workspace running.
- Screenshot: truffle migratesuccess (showing KYC address).
- Screenshot: Truffle console after adding banks/customers + verifying one.
- Screenshot: Web UI (tables populated after your actions).
- Zip: my-project/excludingnode_modules. Includefrontend/withindex.html,app.js,package.json,bs-config.json.
TP1_KYC_FirstnameLastname