Full DApp Project
Saatnya menggabungkan semua yang sudah dipelajari menjadi DApp (Decentralized Application) end-to-end. Kita akan membahas arsitektur lengkap dari smart contract sampai frontend.
Arsitektur DApp
// Komponen utama DApp:
//
// ┌─────────────┐ ┌──────────────┐ ┌────────────────┐
// │ Frontend │────▶│ Blockchain │────▶│ Smart Contract │
// │ (React + │ │ (Ethereum/ │ │ (Solidity) │
// │ wagmi) │◀────│ L2) │◀────│ │
// └─────────────┘ └──────────────┘ └────────────────┘
// │ │
// ▼ ▼
// ┌─────────────┐ ┌────────────────┐
// │ IPFS │ │ The Graph │
// │ (Storage) │ │ (Indexing) │
// └─────────────┘ └────────────────┘
Project Structure
my-dapp/
├── contracts/ # Solidity smart contracts
│ ├── src/
│ │ └── MyContract.sol
│ ├── test/
│ │ └── MyContract.t.sol
│ ├── script/
│ │ └── Deploy.s.sol
│ └── hardhat.config.ts
├── frontend/ # React frontend
│ ├── src/
│ │ ├── config/
│ │ │ └── wagmi.ts # Chain & connector config
│ │ ├── hooks/
│ │ │ └── useMyContract.ts # Custom contract hooks
│ │ ├── components/
│ │ │ ├── ConnectButton.tsx
│ │ │ ├── MintForm.tsx
│ │ │ └── TokenList.tsx
│ │ ├── abi/
│ │ │ └── MyContract.json # Generated ABI
│ │ └── App.tsx
│ └── package.json
├── subgraph/ # The Graph indexing
│ ├── schema.graphql
│ ├── src/mapping.ts
│ └── subgraph.yaml
└── README.md
Development Workflow
// 1. WRITE & TEST SMART CONTRACT
npx hardhat compile
npx hardhat test
npx hardhat coverage // Aim for 100% coverage
// 2. DEPLOY TO TESTNET
npx hardhat run scripts/deploy.ts --network sepolia
// → Contract address: 0x123...
// → Verify di Etherscan
// 3. GENERATE ABI & TYPES
// Copy ABI dari artifacts/ ke frontend/src/abi/
// Atau gunakan wagmi CLI: wagmi generate
// 4. BUILD FRONTEND
// Setup wagmi config, connect wallet, read/write contract
// 5. DEPLOY SUBGRAPH (opsional)
graph codegen && graph build
graph deploy --studio my-subgraph
// 6. TEST END-TO-END
// Connect wallet → interact → verify on explorer
Contoh: NFT Minting DApp
// Smart Contract (simplified)
contract NFTDApp is ERC721URIStorage, Ownable {
uint256 public mintPrice = 0.01 ether;
uint256 public totalMinted;
uint256 public constant MAX_SUPPLY = 1000;
function mint(string calldata uri) external payable {
require(totalMinted < MAX_SUPPLY, "Sold out");
require(msg.value >= mintPrice, "Insufficient ETH");
_safeMint(msg.sender, totalMinted);
_setTokenURI(totalMinted, uri);
totalMinted++;
}
function withdraw() external onlyOwner {
payable(owner()).transfer(address(this).balance);
}
}
// Frontend Hook
function useMintNFT() {
const { writeContract, data: hash } = useWriteContract();
const { isSuccess } = useWaitForTransactionReceipt({ hash });
const mint = async (metadataURI: string) => {
writeContract({
address: CONTRACT_ADDRESS,
abi: nftAbi,
functionName: "mint",
args: [metadataURI],
value: parseEther("0.01"),
});
};
return { mint, isSuccess };
}
Deployment Checklist
- Smart Contract: Audit, 100% test coverage, verified on Etherscan
- Frontend: Error handling, loading states, mobile responsive
- RPC: Gunakan reliable provider (Alchemy, Infura), bukan public RPC
- Wallet UX: Support multiple wallets (MetaMask, WalletConnect, Coinbase)
- Network: Detect wrong network, offer switch
- IPFS: Pin semua metadata, gunakan dedicated gateway
- Monitoring: Track contract events, gas usage, error rates
Mainnet Launch
- Deploy ke testnet dan test extensively
- Professional security audit (jika mengelola dana user)
- Deploy ke mainnet (atau L2 untuk gas lebih murah)
- Verify contract di Etherscan
- Setup monitoring (alerts untuk suspicious transactions)
- Document everything (README, contract addresses, ABI)