Реализация подключения криптокошелька к веб-приложению

Наша компания занимается разработкой, поддержкой и обслуживанием сайтов любой сложности. От простых одностраничных сайтов до масштабных кластерных систем построенных на микро сервисах. Опыт разработчиков подтвержден сертификатами от вендоров.

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Реализация подключения криптокошелька к веб-приложению
Средняя
~3-5 рабочих дней
Часто задаваемые вопросы

Наши компетенции:

Этапы разработки

Последние работы

  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    874
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    851

Реализация подключения криптокошелька к веб-приложению

Подключение кошелька — первая точка входа в любое Web3-приложение. Пользователь нажимает «Connect Wallet», браузер открывает MetaMask или WalletConnect QR, приложение получает адрес и подпись. Звучит просто, но под капотом — три разных протокола, десяток поставщиков кошельков и ряд проблем с состоянием, которые нужно решать правильно с самого начала.

Что происходит при подключении

  1. Браузер проверяет наличие window.ethereum (инжектированные кошельки: MetaMask, Rabby, Brave Wallet)
  2. Приложение вызывает eth_requestAccounts — появляется popup подтверждения
  3. Кошелёк возвращает массив адресов, первый — активный
  4. Приложение подписывает SIWE (Sign-In with Ethereum) сообщение для аутентификации на бэкенде
  5. Сессия создаётся на сервере по подписи

WalletConnect (мобильные кошельки) работает иначе: через relay-сервер, WebSocket и QR-код. Coinbase Wallet поддерживает оба способа.

Минимальная реализация через ethers.js

// lib/wallet.ts
import { BrowserProvider, JsonRpcSigner } from 'ethers';

export interface WalletState {
  address: string | null;
  chainId: number | null;
  provider: BrowserProvider | null;
  signer: JsonRpcSigner | null;
}

export async function connectWallet(): Promise<WalletState> {
  if (!window.ethereum) {
    throw new Error('No injected wallet found. Install MetaMask.');
  }

  const provider = new BrowserProvider(window.ethereum);
  const accounts = await provider.send('eth_requestAccounts', []);
  const network = await provider.getNetwork();
  const signer = await provider.getSigner();

  return {
    address: accounts[0],
    chainId: Number(network.chainId),
    provider,
    signer,
  };
}

export async function switchChain(chainId: number): Promise<void> {
  await window.ethereum.request({
    method: 'wallet_switchEthereumChain',
    params: [{ chainId: `0x${chainId.toString(16)}` }],
  });
}

Обработка событий кошелька

Кошелёк меняет аккаунт или сеть без уведомления приложения — нужно подписаться на события:

// hooks/useWalletEvents.ts
import { useEffect } from 'react';
import { useWalletStore } from '@/store/wallet';

export function useWalletEvents() {
  const { disconnect, setAddress, setChainId } = useWalletStore();

  useEffect(() => {
    if (!window.ethereum) return;

    const handleAccountsChanged = (accounts: string[]) => {
      if (accounts.length === 0) {
        disconnect();
      } else {
        setAddress(accounts[0]);
      }
    };

    const handleChainChanged = (chainIdHex: string) => {
      setChainId(parseInt(chainIdHex, 16));
      // Страницу не перезагружаем — обновляем состояние
    };

    window.ethereum.on('accountsChanged', handleAccountsChanged);
    window.ethereum.on('chainChanged', handleChainChanged);
    window.ethereum.on('disconnect', disconnect);

    return () => {
      window.ethereum.removeListener('accountsChanged', handleAccountsChanged);
      window.ethereum.removeListener('chainChanged', handleChainChanged);
      window.ethereum.removeListener('disconnect', disconnect);
    };
  }, [disconnect, setAddress, setChainId]);
}

SIWE-аутентификация

Адрес кошелька — не идентификатор пользователя сам по себе. Его можно подделать в HTTP-запросе. Для бэкенд-сессии нужна подпись:

// lib/siwe.ts
import { SiweMessage } from 'siwe';

export async function signInWithEthereum(
  address: string,
  chainId: number,
  signer: JsonRpcSigner,
): Promise<{ message: string; signature: string }> {
  const nonce = await fetch('/api/auth/nonce').then(r => r.text());

  const message = new SiweMessage({
    domain: window.location.host,
    address,
    statement: 'Sign in to MyApp',
    uri: window.location.origin,
    version: '1',
    chainId,
    nonce,
  });

  const messageStr = message.prepareMessage();
  const signature = await signer.signMessage(messageStr);

  return { message: messageStr, signature };
}

Бэкенд верифицирует подпись через siwe пакет (Node.js) или любую реализацию ecrecover. Nonce в Redis с TTL 5 минут — защита от replay-атак.

Множество кошельков через универсальный провайдер

Для поддержки MetaMask, WalletConnect, Coinbase Wallet без custom logic для каждого — используется @web3-onboard или стек wagmi + viem. Минимальный пример с @web3-onboard:

import Onboard from '@web3-onboard/core';
import injectedModule from '@web3-onboard/injected-wallets';
import walletConnectModule from '@web3-onboard/walletconnect';

const injected = injectedModule();
const walletConnect = walletConnectModule({
  projectId: process.env.NEXT_PUBLIC_WC_PROJECT_ID!,
  requiredChains: [1, 137],
});

export const onboard = Onboard({
  wallets: [injected, walletConnect],
  chains: [
    { id: '0x1', token: 'ETH', label: 'Ethereum Mainnet', rpcUrl: process.env.ETH_RPC_URL! },
    { id: '0x89', token: 'MATIC', label: 'Polygon', rpcUrl: process.env.POLYGON_RPC_URL! },
  ],
  appMetadata: {
    name: 'MyApp',
    icon: '/logo.svg',
    description: 'DeFi platform',
  },
});

Персистентность подключения

После перезагрузки страницы состояние кошелька нужно восстанавливать без повторного popup:

// Проверка при инициализации
async function restoreConnection(): Promise<void> {
  if (!window.ethereum) return;

  // eth_accounts (не eth_requestAccounts) — не вызывает popup
  const accounts: string[] = await window.ethereum.request({
    method: 'eth_accounts',
  });

  if (accounts.length > 0) {
    // Кошелёк уже авторизован — восстанавливаем состояние
    const provider = new BrowserProvider(window.ethereum);
    const network = await provider.getNetwork();
    walletStore.set({ address: accounts[0], chainId: Number(network.chainId) });
  }
}

Срок реализации: базовое подключение MetaMask + WalletConnect с SIWE-аутентификацией — 2–3 дня. Включая обработку событий, персистентность и поддержку 3–4 кошельков через @web3-onboard3–5 дней.