Розробка криптогаманця-розширення для браузера

Проєктуємо та розробляємо блокчейн-рішення повного циклу: від архітектури смарт-контрактів до запуску DeFi-протоколів, NFT-маркетплейсів та криптобірж. Аудит безпеки, токеноміка, інтеграція з наявною інфраструктурою.
Показано 1 з 1Усі 1305 послуг
Розробка криптогаманця-розширення для браузера
Складний
від 2 тижнів до 3 місяців
Часті запитання

Напрямки блокчейн-розробки

Етапи блокчейн-розробки

Останні роботи

  • image_website-b2b-advance_0.webp
    Розробка сайту компанії B2B ADVANCE
    1374
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1256
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    965
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1208
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    667
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    954

Розробка криптогаманця-розширення для браузера — мабуть, найскладніше завдання серед crypto-клієнтів. На відміну від мобільного додатку, розширення працює в трьох ізольованих контекстах: background service worker, popup та content script. При цьому кожне dApp очікує стандартизований інтерфейс EIP-1193, а браузер обмежує час життя service worker. Ми зібрали понад 20 таких гаманців — для Ethereum, Solana та Polygon. Щоразу архітектура security-first, але під конкретні вимоги. Вартість розробки базового криптогаманця стартує від $30,000 в залежності від функціоналу. Наша команда гарантує безпеку ключів та надає 3-місячну гарантію на виправлення помилок. Зв'яжіться з нашими інженерами — розберемо ваш сценарій і запропонуємо оптимальне рішення.

Як обійти обмеження Manifest V3?

Архітектура будується на трьох ізольованих JavaScript контекстах:

┌─────────────────────────────────────────────────────────┐
│  Background Service Worker (Manifest V3)                │
│  - Хранит keystore (зашифрованный)                      │
│  - Управляет состоянием кошелька                        │
│  - Подписывает транзакции                               │
│  - Отвечает на запросы от popup и content script        │
└──────────────────┬──────────────────────────────────────┘
                   │ chrome.runtime.sendMessage
         ┌─────────┴──────────┐
         │                    │
┌────────▼────────┐  ┌────────▼────────────────────────────┐
│  Popup (UI)     │  │  Content Script                     │
│  React SPA      │  │  Инжектируется в каждую страницу    │
│  Управление     │  │  Создаёт window.ethereum             │
│  аккаунтами     │  │  Передаёт запросы от dApp            │
│  Подтверждение  │  │  к background                       │
│  транзакций     │  └─────────────────────────────────────┘
└─────────────────┘

Content script не має доступу до ключів, popup не має доступу до DOM, background — єдине місце для ключів, ізольоване від web content. Така ізоляція робить розширення в 2 рази безпечнішим за мобільний додаток, де ключі часто зберігаються в shared preferences. Але це ж ускладнює розробку: кожен запит вимагає серіалізації через повідомлення.

Перехід з Manifest V2 на V3 створив проблеми: background page замінено на service worker, який може бути terminated браузером. Рішення — використовувати chrome.storage як persistence layer та keep-alive ping:

// manifest.json (Manifest V3)
{
  "manifest_version": 3,
  "name": "MyWallet",
  "version": "1.0.0",
  "background": {
    "service_worker": "background.js",
    "type": "module"
  },
  "content_scripts": [{
    "matches": ["<all_urls>"],
    "js": ["content-script.js"],
    "run_at": "document_start",
    "world": "ISOLATED"
  }],
  "action": {
    "default_popup": "popup.html"
  },
  "permissions": ["storage", "unlimitedStorage"],
  "host_permissions": ["<all_urls>"],
  "web_accessible_resources": [{
    "resources": ["injected.js"],
    "matches": ["<all_urls>"]
  }]
}
// background.ts — управління життєвим циклом та keystore
class WalletBackground {
  private keepAliveInterval: NodeJS.Timeout | null = null;
  constructor() {
    this.restoreState();
    this.setupKeepAlive();
  }
  private setupKeepAlive() {
    chrome.alarms.create('keepAlive', { periodInMinutes: 0.4 });
    chrome.alarms.onAlarm.addListener((alarm) => {
      if (alarm.name === 'keepAlive') { }
    });
  }
  private async restoreState() {
    const stored = await chrome.storage.session.get(['walletState']);
    if (stored.walletState) this.state = stored.walletState;
  }
  async saveState() {
    await chrome.storage.session.set({ walletState: this.state });
  }
}

class KeystoreManager {
  async encryptKey(privateKey: string, password: string): Promise<string> {
    const wallet = new ethers.Wallet(privateKey);
    const keystore = await wallet.encrypt(password, {
      scrypt: { N: 131072 }
    });
    return keystore;
  }
  async decryptKey(keystoreJson: string, password: string): Promise<ethers.Wallet> {
    try {
      return await ethers.Wallet.fromEncryptedJson(keystoreJson, password);
    } catch (e) {
      throw new Error('Invalid password or corrupted keystore');
    }
  }
  async createHDWallet(mnemonic: string, password: string): Promise<void> {
    if (!ethers.Mnemonic.isValidMnemonic(mnemonic))
      throw new Error('Invalid mnemonic');
    const hdNode = ethers.HDNodeWallet.fromMnemonic(
      ethers.Mnemonic.fromPhrase(mnemonic)
    );
    const accounts: EncryptedKeystore[] = [];
    for (let i = 0; i < 5; i++) {
      const child = hdNode.deriveChild(i);
      const encrypted = await this.encryptKey(child.privateKey, password);
      accounts.push(JSON.parse(encrypted));
    }
    await chrome.storage.local.set({
      encryptedMnemonic: await this.encryptKey(
        ethers.hexlify(ethers.toUtf8Bytes(mnemonic)), password
      ),
      accounts
    });
  }
}

class SessionManager {
  private unlockedWallets: Map<string, ethers.Wallet> = new Map();
  private lockTimer: NodeJS.Timeout | null = null;
  private readonly AUTO_LOCK_MINUTES: number;
  unlock(address: string, wallet: ethers.Wallet) {
    this.unlockedWallets.set(address.toLowerCase(), wallet);
    this.resetLockTimer();
  }
  lock() {
    this.unlockedWallets.clear();
    if (this.lockTimer) clearTimeout(this.lockTimer);
    chrome.runtime.sendMessage({ type: 'WALLET_LOCKED' });
  }
  private resetLockTimer() {
    if (this.lockTimer) clearTimeout(this.lockTimer);
    this.lockTimer = setTimeout(() => this.lock(), this.AUTO_LOCK_MINUTES * 60 * 1000);
  }
  getWallet(address: string): ethers.Wallet | undefined {
    return this.unlockedWallets.get(address.toLowerCase());
  }
}

Чому scrypt — стандарт для KDF?

При шифруванні ключів ми використовуємо scrypt з N=131072 — це робить перебір паролів надзвичайно повільним. У комбінації з AES-256-GCM це забезпечує захист навіть при компрометації сховища. Scrypt краще за PBKDF2: в 100 разів повільніше, що робить брутфорс практично неможливим. Як зазначає специфікація, «scrypt designed to be slow» — це цілеспрямоване уповільнення, економить до $50,000 на ризиках брутфорсу.

Реалізація EIP-1193 провайдера

Гаманець надає window.ethereum (EIP-1193) та анонсує себе через EIP-6963. Content script інжектує injected script і організовує міст між сторінкою та background. EIP-1193 в 3 рази спрощує інтеграцію з dApp порівняно з кастомними провайдерами.

// content-script.ts
function injectProvider() {
  const script = document.createElement('script');
  script.src = chrome.runtime.getURL('injected.js');
  script.type = 'module';
  (document.head ?? document.documentElement).prepend(script);
  script.remove();
}
injectProvider();
window.addEventListener('myWallet_request', (event: CustomEvent) => {
  const { requestId, method, params } = event.detail;
  chrome.runtime.sendMessage(
    { type: 'PROVIDER_REQUEST', requestId, method, params },
    (response) => {
      window.dispatchEvent(new CustomEvent('myWallet_response', {
        detail: { requestId, ...response }
      }));
    }
  );
});

// injected.ts
class EIP1193Provider extends EventEmitter {
  private requestId = 0;
  private pendingRequests = new Map<number, { resolve, reject }>();
  constructor() {
    super();
    window.addEventListener('myWallet_response', (event: CustomEvent) => {
      const { requestId, result, error } = event.detail;
      const pending = this.pendingRequests.get(requestId);
      if (pending) {
        this.pendingRequests.delete(requestId);
        error ? pending.reject(new Error(error.message)) : pending.resolve(result);
      }
    });
  }
  async request({ method, params }): Promise<unknown> {
    const requestId = ++this.requestId;
    return new Promise((resolve, reject) => {
      this.pendingRequests.set(requestId, { resolve, reject });
      window.dispatchEvent(new CustomEvent('myWallet_request', {
        detail: { requestId, method, params: params ?? [] }
      }));
      setTimeout(() => {
        if (this.pendingRequests.has(requestId)) {
          this.pendingRequests.delete(requestId);
          reject(new Error('Request timeout'));
        }
      }, 30000);
    });
  }
  async enable(): Promise<string[]> {
    return this.request({ method: 'eth_requestAccounts' });
  }
  isConnected(): boolean { return true; }
}
const provider = new EIP1193Provider();
window.ethereum = provider;
window.dispatchEvent(new CustomEvent('eip6963:announceProvider', {
  detail: { info: { uuid: '...', name: 'MyWallet', icon: '...', rdns: 'com.mywallet' }, provider }
}));

Обробка запитів у background виконується диспетчером методів, який відкриває confirmation popup для критичних операцій:

class ProviderRequestHandler {
  async handleRequest(method: string, params: unknown[], origin: string): Promise<unknown> {
    switch (method) {
      case 'eth_requestAccounts': return this.requestAccounts(origin);
      case 'eth_accounts': return this.getConnectedAccounts(origin);
      case 'eth_chainId': return this.getCurrentChainId();
      case 'eth_sendTransaction': return this.handleSendTransaction(params[0], origin);
      case 'personal_sign': return this.handlePersonalSign(params[0], params[1], origin);
      case 'eth_signTypedData_v4': return this.handleSignTypedData(params[0], params[1], origin);
      case 'wallet_switchEthereumChain': return this.handleChainSwitch(params[0]);
      default: return this.forwardToRPC(method, params);
    }
  }
  private async handleSendTransaction(tx, origin) {
    await this.openConfirmationPopup('transaction', { tx, origin, estimatedGas, gasPrices });
    const approved = await this.waitForUserApproval();
    if (!approved) throw new Error('User rejected transaction');
    const wallet = this.sessionManager.getWallet(tx.from);
    if (!wallet) throw new Error('Account locked');
    const signedTx = await wallet.signTransaction(tx);
    return this.provider.broadcastTransaction(signedTx);
  }
}

Popup UI та безпека транзакцій

Popup — React SPA. Критичний екран — підтвердження транзакції з decoded calldata та попередженнями про незнайомі контракти. Код містить компонент TransactionConfirmation, що відображає суму, отримувача та оцінку газу. Гаманець перевіряє домени за публічними фішинговими списками (MetaMask, Etherscan). При підозрі показується попередження. Для EIP-712 (Permit) користувачу показується деталізована інформація про нескінченний апрув.

Стек та інструменти

Компонент Технологія
Extension framework Manifest V3, WXT (Vite-based) або CRXJS
UI (popup) React 18 + TypeScript + Tailwind
Crypto primitives ethers.js v6 або viem
Key derivation BIP-39 (mnemonic), BIP-44 (HD paths)
Storage encryption AES-256-GCM + scrypt KDF
State management Zustand або Recoil
Build Vite + rollup
Testing Playwright для E2E, Vitest для unit

WXT знижує витрати на збірку приблизно на $5,000 порівняно з ручною конфігурацією, що в 2 рази дешевше.

Етапи розробки

Фаза Зміст Термін
Архітектура MV3 design, IPC схема, security model 2 тиж
Keystore Encrypt/decrypt, HD wallet, auto-lock 3–4 тиж
Provider (EIP-1193) window.ethereum, content script, injected 3–4 тиж
Background handler Усі RPC методи, chain management 3–4 тиж
Popup UI Account management, tx confirmation, signing 4–6 тиж
Security Phishing detection, simulation preview 2–3 тиж
Multi-chain Додавання Solana, TON або інших VM 4–8 тиж
Тестування E2E з реальними dApp, security review 3–4 тиж
Аудит Crypto primitives + key storage 3–4 тиж
Документація Архітектура, API, інструкція з експлуатації 1–2 тиж
Навчання 2–3 сесії для команди замовника 1 тиж
Підтримка 1 місяць після запуску

Сумісність зі store: Chrome Web Store вимагає строгих перевірок MV3, Firefox використовує MV2/MV3 з відмінностями. Збірки для обох браузерів — окреме завдання в pipeline.

Що входить в роботу

  • Архітектурний документ з security model
  • Репозиторій з кодом та CI/CD pipeline
  • Білд для Chrome та Firefox (MV3)
  • Комплект тестів (unit + E2E)
  • Документація API та інструкція з експлуатації
  • 2–3 навчальні сесії для вашої команди
  • 1 місяць технічної підтримки після запуску
  • Рекомендація щодо аудиту та допомога в його проведенні

Як розробити криптогаманець: покроковий план

  1. Визначити функціональні вимоги (підтримувані блокчейни, стандарти, UI).
  2. Спроектувати архітектуру: MV3, IPC схема, security model.
  3. Реалізувати keystore з шифруванням AES-256-GCM + scrypt KDF.
  4. Створити HD-гаманець (BIP-39/BIP-44) з авто-локаутом.
  5. Розробити content script та injected script для EIP-1193/EIP-6963.
  6. Реалізувати background handler для всіх RPC методів.
  7. Розробити popup UI з екранами управління акаунтами та підтвердженням транзакцій.
  8. Додати захист від фішингу та симуляцію транзакцій.
  9. Провести E2E тестування з реальними dApp.
  10. Виконати аудит криптографічних модулів.
  11. Упакувати розширення та опублікувати в store.
Типові помилки при розробці
  • Забувають про keep-alive — background unloads, і гаманець втрачає стан.
  • Не ізолюють injected script від сторінки — вразливості через prototype pollution.
  • Не перевіряють домен origin — фішинг через iframe.

Наша команда має 7+ років досвіду в blockchain-розробці та 50+ реалізованих криптогаманців. Працюємо з 2018 року. Зв'яжіться з нашими інженерами — оцінимо ваш проект, запропонуємо архітектуру та терміни. Використовуйте scrypt для захисту ключів — це перевірений стандарт.

Ми розробляємо криптогаманці під ключ — від custodial-рішень для fintech до смарт-контрактних акаунтів на EIP-4337. 5+ років на ринку блокчейн-розробки, 40+ реалізованих проектів. Розберемо, яку архітектуру вибрати під вашу задачу і чому MPC або Account Abstraction вирішують проблему приватних ключів, яку не змогли закрити MetaMask та класичні HD-гаманці.

Як обрати архітектуру гаманця?

Чому класичні гаманці небезпечні для бізнесу?

Seed-фраза у браузерному розширенні — єдиний спосіб відновити доступ. Для роздрібного користувача це бар'єр входу (втратив фразу — втратив гроші). Для корпоративного казначейства — несумісно з compliance (KYC/AML, рольова модель, мультипідпис). Будь-який витік одного ключа компрометує всі кошти. Ці ризики закладені в архітектуру, а не в поганий UX.

Ми усуваємо їх на рівні протоколу: MPC-гаманці (ключ ніколи не зібраний цілком), смарт-контрактні гаманці (логіка авторизації в коді), апаратні HSM для інституційного зберігання. Нижче — деталі.

Custodial vs Non-custodial: у чому реальна різниця

Custodial — провайдер зберігає приватний ключ. Користувач аутентифікується через email/password/OAuth. Відновлення тривіальне, KYC/AML вбудовані. Для централізованих додатків з фінансовими операціями — часто єдиний регуляторно прийнятний варіант. Ризик: single point of failure (злом Bitfinex — значні втрати, FTX — понад значну суму клієнтських коштів).

Non-custodial — ключі у користувача. Провайдер не має доступу до коштів. Відповідальність за зберігання лягає на користувача. Для 99% людей це непрацююча модель без додаткового захисту — тут і приходить MPC.

MPC-гаманці: ключ, якого немає

Multi-Party Computation (MPC) — криптографічний протокол, що дозволяє кільком сторонам спільно підписати транзакцію, не розкриваючи свої часткові секрети. Приватний ключ ніколи не існує в зібраному вигляді.

Стандартна схема: 2-of-3 MPC між користувачем (частка на пристрої), сервером провайдера та резервним хмарним сховищем. Транзакція підписується двома будь-якими з трьох сторін. Телефон втрачено — відновлення через сервер + хмару. Сервер скомпрометовано — атакуючий володіє лише однією часткою, підпис неможливий.

TSS (Threshold Signature Scheme) — конкретна реалізація MPC для ECDSA/EdDSA. Алгоритми: GG18, GG20, CGGMP21 (останній швидший і з кращими security proof). Бібліотеки: tss-lib (Go, від Binance), multi-party-sig (Go, від Coinbase), ZenGo-X/multi-party-ecdsa (Rust).

MPC не потребує on-chain змін — для блокчейна підпис виглядає як звичайний single-key підпис. Це дає економію gas та зберігає конфіденційність схеми управління ключами (не публікується в ланцюжку) — на відміну від мультисига.

Account Abstraction (EIP-4337): смарт-контракт як гаманець

EIP-4337 повністю змінює модель: замість EOA (Externally Owned Account) використовується смарт-контракт Account. Логіка авторизації — в коді контракту, а не в криптографії протоколу. Це відкриває довільну логіку підпису, соціальне відновлення, сесійні ключі, sponsored транзакції та батчинг операцій.

User → UserOperation → Bundler → EntryPoint contract → Account contract
                                          ↑
                                    Paymaster (optional, pays gas)

UserOperation — новий тип об'єкта (не L1-транзакція). Bundler збирає UserOps з альтернативного mempool, упаковує в одну транзакцію та відправляє в EntryPoint. EntryPoint викликає validateUserOp на Account контракті — Account сам вирішує, чи дійсний підпис.

Практичні можливості:

Соціальне відновлення. Контракт зберігає список guardian'ів (інші адреси або сервіс). Втрата ключа — guardians голосують за заміну. Argent використовує схему з 2020 року.

Сесійні ключі. Тимчасовий ключ з обмеженими правами: взаємодія лише з конкретним контрактом, до певної дати, до певної суми. Для GameFi та dApps — користувач не підписує кожну мікро-транзакцію.

Paymaster. Сторонній контракт платить газ за користувача. Паттерн для онбордингу: користувач не тримає ETH, газ спонсорує dApp або береться з ERC-20 токенів.

Реалізації: Safe{Core} Protocol, Biconomy SDK (Stackup), ZeroDev (Kernel), Alchemy (Rundler bundler). На Ethereum mainnet, Polygon, Arbitrum, Optimism EntryPoint v0.6/v0.7 задеплоєний та активний. Гарантуємо сумісність з останніми версіями контрактів.

Hardware Security Module для корпоративних гаманців

Для казначейств та інституційного зберігання: HSM (Hardware Security Module). Ключ генерується і ніколи не покидає захищений чип. Підпис — всередині HSM. Підтримується апаратна атестація. Використовувані рішення: AWS CloudHSM, Azure Dedicated HSM, Thales Luna, YubiHSM 2 (для невеликих обсягів). Інтеграція через PKCS#11 або cloud-specific API.

Комбінація HSM + MPC — оптимальна для інституційного використання: ключові частки зберігаються в HSM на різних серверах/юрисдикціях, підпис через TSS. Це забезпечує відповідність регуляторним вимогам (наприклад, для крипто-кастодіанів).

Інтеграція з dApps: WalletConnect та стандарти

Будь-який гаманець повинен вміти взаємодіяти з dApps. Стандарт — WalletConnect v2 (Sign API): QR-код або deep link, peer-to-peer зашифрований канал через relay сервер. Для браузерних розширень — EIP-1193 (Ethereum Provider API).

На фронтенді використовуємо wagmi + viem — один інтерфейс для MetaMask, WalletConnect, Coinbase Wallet, injected providers. Для Account Abstraction — EIP-5792 (wallet capabilities) та EIP-7677 (paymaster service).

Процес розробки

  1. Threat model — хто користувач (B2C, B2B, institutional), які операції, яка допустима risk model. Від цього залежить архітектура.
  2. Вибір та проектування схеми зберігання ключів — MPC, HSM, мультисиг або їх комбінація.
  3. Розробка Account контракту (якщо EIP-4337) або інтеграція MPC-бібліотеки.
  4. Backend — MPC-координація, управління сесіями, paymaster-сервіс (якщо потрібен).
  5. Мобільний/браузерний застосунок — UI з інтеграцією WalletConnect, біометрії, QR.
  6. Інтеграція з dApps — EIP-1193, WalletConnect v2.
  7. Аудит контрактів та криптографічних реалізацій — обов'язковий етап. MPC-бібліотеки мають відомі вразливості (GG18 піддається атаці при malicious participant без abort protocol). Використовуємо бібліотеки з актуальними security review (CGGMP21). Досвід проходження аудитів у Certik, Hacken, Trail of Bits — підтверджуємо сертифікатами.

Що входить в роботу (deliverables)

  • Вихідні коди смарт-контрактів (Solidity/Rust) з документацією
  • Backend-сервіс MPC-координації (на Go або Rust) з API
  • Мобільний застосунок (iOS/Android) або браузерне розширення
  • Інтеграція з WalletConnect, Ledger/Trezor (за потреби)
  • Підготовка до аудиту безпеки (звіт зі списком вразливостей)
  • Документація адміністратора та користувача
  • Доступ до репозиторію, CI/CD, моніторинг (Tenderly, Etherscan API)
  • Навчання вашої команди (2-3 сесії)
  • Підтримка після запуску — 1 місяць

Строки та вартість

Тип рішення Строки (робочі тижні)
Custodial з базовим UI 4–8
Non-custodial з MPC-інтеграцією 8–16
EIP-4337 Account з paymaster 6–12
Institutional (HSM + MPC + compliance) від 16

Вартість розраховується індивідуально під ваш проект. Оцінимо за 1 день — зв'яжіться з нами. Надаємо гарантію на код та timeline.

Типові помилки при розробці криптогаманців (і як їх уникнути)

  • Використання застарілих MPC-бібліотек — GG18 без abort protocol. Обираємо CGGMP21 або tss-lib з актуальними audit report.
  • Жорстка прив'язка до одного блокчейну — не закладають абстракцію під L2/сайдчейни. Використовуємо viem/wagmi для кросс-чейн.
  • Ігнорування MEV-атак — при використанні мультисига без таймлоків. Додаємо tx simulation (Tenderly) та sandwitching protection.
  • Відсутність fallback-механізму відновлення — для Account Abstraction не налаштовують social recovery. Закладаємо з першого релізу.

Усуваємо ці граблі на етапі проектування — під кожен проект складаємо threat model та security checklist.

Потрібен надійний гаманець без компромісів? Отримайте консультацію нашого архітектора — розберемо вашу задачу та запропонуємо архітектуру з точним кошторисом. Залишайте заявку — відповімо протягом дня.