بی باگکد بنویس، از باگ نترس
  1. بی باگ
  2. مقالات
  3. وب۳
  4. اتصال کیف پول

کیف پول را وصل کن: وب۳ برای برنامه نویس فرانت اند

بدون قیمت ارز و بدون شعار آینده اینترنت. فقط همان چیزی که لازم است تا یک رابط وب واقعی با بلاک چین حرف بزند و وقتی کاربر تراکنش را کنسل کرد، رابطت از هم نپاشد.

کان دو ۱۲ دقیقه ۱۲ مرداد ۱۴۰۴ ۲٫۴ هزار بازدید ethers نسخه ۶
نمای رابط وب متصل به کیف پول

بیشتر آموزش های وب۳ فارسی از جای اشتباهی شروع می شوند: از قیمت و صرافی. برای یک برنامه نویس فرانت اند، وب۳ فقط یک چیز است: یک API عجیب که در مرورگر کاربر تزریق شده، امضای دیجیتال می خواهد، چند ثانیه تاخیر دارد و هر درخواستش می تواند پول خرج کند. همین. اگر این را بپذیری، بقیه ماجرا مهندسی معمولی است.

پیش نیاز

جاوااسکریپت مدرن، async و await، و یک کیف پول مرورگری نصب شده. سالیدیتی لازم نیست. در این مقاله قرارداد نمی نویسیم، فقط با آن حرف می زنیم.

سه لایه ای که هر dApp روی آن سوار است

هر اپلیکیشن غیرمتمرکز، هر قدر هم پیچیده، از همین سه لایه ساخته می شود:

  1. Provider: اتصال فقط خواندنی به شبکه. وضعیت را می خواند و هزینه ای ندارد.
  2. Signer: نماینده کاربر. تنها چیزی که می تواند تراکنش امضا کند.
  3. Contract: یک آبجکت جاوااسکریپتی که از آدرس و ABI ساخته می شود.
کلید خصوصی هرگز از کیف پول بیرون نمی آید. کد تو فقط درخواست امضا می دهد و منتظر بله یا نه کاربر می ماند.قاعده اول امنیت در فرانت اند وب۳

قدم اول: اتصال، بدون خراب کاری

هیچ وقت فرض نکن کیف پول نصب است. هیچ وقت هم بدون کلیک کاربر درخواست اتصال نفرست. کیف پول ها این رفتار را اسپم حساب می کنند.

connect.js · ethers v6
import { BrowserProvider } from "ethers";

export async function connectWallet() {
  if (!window.ethereum) {
    throw new Error("کیف پولی پیدا نشد");
  }

  const provider = new BrowserProvider(window.ethereum);
  const [account] = await provider.send("eth_requestAccounts", []);
  const signer = await provider.getSigner();
  const { chainId, name } = await provider.getNetwork();

  return { provider, signer, account, chainId, network: name };
}

کاربر می تواند وسط کار حساب یا شبکه را عوض کند. اگر گوش ندهی، رابطت دیتای حساب دیگری را نشان می دهد.

watch.js
window.ethereum?.on("accountsChanged", (accounts) => {
  accounts.length ? setAccount(accounts[0]) : signOut();
});

window.ethereum?.on("chainChanged", () => location.reload());
باگی که همه می خورند

آدرس ها را برای مقایسه با toLowerCase() یکدست کن. کیف پول ها آدرس را با حروف بزرگ و کوچک ترکیبی برمی گردانند و مساوی ساده بی رحمانه false می دهد.

قدم دوم: خواندن از قرارداد

خواندن با provider انجام می شود، نه signer. یعنی حتی بدون اتصال کیف پول هم می توانی داده نشان بدهی. برای صفحه اول سایت این خیلی مهم است.

read.js
import { Contract, formatUnits } from "ethers";

const ABI = [
  "function balanceOf(address) view returns (uint256)",
  "function decimals() view returns (uint8)",
  "function symbol() view returns (string)",
];

export async function getBalance(provider, token, wallet) {
  const contract = new Contract(token, ABI, provider);
  const [raw, decimals, symbol] = await Promise.all([
    contract.balanceOf(wallet),
    contract.decimals(),
    contract.symbol(),
  ]);
  return `${formatUnits(raw, decimals)} ${symbol}`;
}

عددهای بلاک چین BigInt هستند، نه Number. اگر آن ها را داخل parseFloat بیندازی، روی مبالغ بزرگ دقت را از دست می دهی.

قدم سوم: ارسال تراکنش و خطاهایی که واقعا می افتند

تراکنش سه حالت دارد: رد شدن توسط کاربر، شکست در شبکه، و موفقیت با تاخیر. هر سه را باید در رابطت نشان بدهی.

mint.js
import { parseEther } from "ethers";

async function mint(contract) {
  setState("waiting-signature");
  try {
    const tx = await contract.mint(1n, { value: parseEther("0.01") });
    setState("pending", tx.hash);
    const receipt = await tx.wait();
    setState("done", receipt.transactionHash);
  } catch (err) {
    if (err.code === 4001) return setState("idle");
    setState("error", err.shortMessage || "تراکنش شکست خورد");
  }
}

لینک explorer را همان لحظه که tx.hash را گرفتی نشان بده. کاربر دوست ندارد روی یک دکمه بی جان خیره شود و نداند چه خبر است.

چک لیست رابط کاربری

وضعیت چیزی که باید نشان بدهی
قبل از اتصال یک دکمه واضح و توضیح کوتاه
در انتظار امضا پیام واضح که پنجره کیف پول باز شده
در انتظار تایید شبکه لینک تراکنش و وضعیت pending
خطا پیام انسانی، نه آبجکت خام خطا
موفق تایید نهایی و آپدیت داده ها

همین پنج مورد اگر درست اجرا شوند، محصولت از نود درصد نمونه کارهای دم دستی وب۳ بهتر است.

CD

درباره نویسنده

چیزهایی که خودم موقع ساختن پروژه ها یاد می گیرم را همان جا می نویسم. نه برای این که کامل ترین مرجع باشم، برای این که موقع گیر کردن به درد بخورم.

جاوااسکریپتفرانت اندوب۳RTL
بعدی برای خواندن

مقاله های مرتبط

فرانت اند

ethers یا viem؟

مقایسه ای که وقت انتخاب کتابخانه نجاتت می دهد.

هر شنبه، یک ایمیل کوتاه

خلاصه مقاله های هفته و یک باگ واقعی. بدون تبلیغ.