Проектування dApp архітектури
dApp архітектура — це не просто "React фронтенд + smart contract". Це продумана система, де frontend, indexer, wallet інтеграція і контракти працюють як одне ціле з хорошим UX. Типова помилка: розробляти frontend окремо від контрактної архітектури — потім виявляється, що UI не може ефективно читати потрібні дані.
Ключові компоненти dApp
Smart Contract Layer
Контракти проектуються з урахуванням frontendability:
- Багаті Events для індексування (всі важливі дії логуються)
- View функції для читання без газу
- Multicall сумісність
State Management
// Сучасний dApp stack: wagmi v2 + viem + TanStack Query
import { useReadContract, useWriteContract, useWaitForTransactionReceipt } from "wagmi";
import { formatUnits } from "viem";
function PoolStats() {
const { data: tvl } = useReadContract({
address: POOL_ADDRESS,
abi: POOL_ABI,
functionName: "totalAssets",
query: { refetchInterval: 30_000 }, // оновлюємо кожні 30 секунд
});
const { data: userBalance } = useReadContract({
address: POOL_ADDRESS,
abi: POOL_ABI,
functionName: "balanceOf",
args: [address],
});
return (
<div>
<p>TVL: {tvl ? formatUnits(tvl, 18) : "Loading..."} ETH</p>
<p>Ваш баланс: {userBalance ? formatUnits(userBalance, 18) : "0"}</p>
</div>
);
}
Batch RPC calls (Multicall3)
Уникнути N окремих RPC запросів через batching:
import { multicall } from "viem/actions";
// Замість 10 окремих запросів — один
const results = await multicall(client, {
contracts: [
{ address: TOKEN_A, abi: ERC20_ABI, functionName: "balanceOf", args: [user] },
{ address: TOKEN_B, abi: ERC20_ABI, functionName: "balanceOf", args: [user] },
{ address: POOL, abi: POOL_ABI, functionName: "totalAssets" },
// ...ще 7 запросів
],
});
Transaction flow UX
function DepositButton({ amount }: { amount: bigint }) {
const { data: hash, writeContract, isPending } = useWriteContract();
const { isLoading: isConfirming, isSuccess } = useWaitForTransactionReceipt({ hash });
// Стани: idle → pending (wallet) → confirming (chain) → success/error
const status = isPending ? "WAITING_WALLET"
: isConfirming ? "CONFIRMING"
: isSuccess ? "SUCCESS"
: "IDLE";
return (
<button
onClick={() => writeContract({ address: POOL, abi, functionName: "deposit", args: [amount] })}
disabled={status !== "IDLE"}
>
{status === "WAITING_WALLET" && "Підтвердіть у гаманці..."}
{status === "CONFIRMING" && "Підтвердження..."}
{status === "SUCCESS" && "Депозит здійснено!"}
{status === "IDLE" && "Депозит"}
</button>
);
}
Data fetching архітектура
Realtime (< 1 sec latency): WebSocket до RPC або Alchemy SDK
Recent history (останні 1000 events): The Graph (subgraph)
Historical analytics: Self-hosted PostgreSQL indexer
Prices: CoinGecko API + Chainlink on-chain
Wallet connection
// RainbowKit конфігурація
import { getDefaultConfig, RainbowKitProvider } from "@rainbow-me/rainbowkit";
import { arbitrum, mainnet, base } from "wagmi/chains";
const config = getDefaultConfig({
appName: "MyDApp",
projectId: WALLETCONNECT_PROJECT_ID,
chains: [mainnet, arbitrum, base],
wallets: [
{ groupName: "Popular", wallets: [metaMaskWallet, coinbaseWallet, walletConnectWallet] },
],
});
Проектування dApp архітектури з урахуванням всіх шарів: 1-2 тижні. Включає wireframes контрактної взаємодії, data flow діаграми, вибір frontend stack і UX flow документацію.







