Non-Custodial Crypto Wallet Development: Secure Key Storage

Seed phrase loss is the leading cause of losing access to crypto assets. Mistakes in key storage implementation lead to irreversible consequences. Unlike custodial solutions where the server stores private keys, we design non-custodial wallets—keys remain on the user's device, encrypted via Secure E

Blockchain Development Services

Frequently Asked Questions

Latest works

  • image_website-b2b-advance_0.webp
    B2B ADVANCE company website development
    1441
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1301
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    998
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1267
  • image_logo-advance_0.webp
    B2B Advance company logo design
    713
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    1003

Seed phrase loss is the leading cause of losing access to crypto assets. Mistakes in key storage implementation lead to irreversible consequences. Unlike custodial solutions where the server stores private keys, we design non-custodial wallets—keys remain on the user's device, encrypted via Secure Enclave or Android Keystore. This is a fundamental difference: improper seed phrase storage renders any beautiful UI meaningless. We do not make such mistakes.

Wallet development falls into two classes: custodial (keys with the service) and non-custodial (keys with the user). The choice affects not only architecture but also legal requirements. According to independent audits, a non-custodial wallet is three times more secure than a custodial one, reducing the risk of breach by up to 90%.

How to Develop a Non-Custodial Wallet?

The standard for non-custodial wallets is HD Wallet (Hierarchical Deterministic, BIP-32/BIP-44). From a single seed phrase (12/24 words BIP-39) we derive a tree of keys. Each chain, each account, each address is a separate child key.

import { ethers } from 'ethers'; import * as bip39 from 'bip39'; const mnemonic = bip39.generateMnemonic(256); const hdNode = ethers.HDNodeWallet.fromPhrase(mnemonic); // m/44'/60'/0'/0/0 — first Ethereum account const wallet = hdNode.derivePath("m/44'/60'/0'/0/0"); console.log(wallet.address); console.log(wallet.privateKey); // NEVER display 

One seed phrase – all wallets for all chains. The user only needs to remember 12 or 24 words.

Why Is On-Device Key Security Important?

The most critical part is private key storage. We use multiple layers of protection: encryption with PBKDF2 + AES-256-GCM, storage in Secure Enclave (iOS) or Android Keystore, and biometric authentication. In browser extensions, we use Chrome's encrypted storage with a password. The private key is in memory only while the wallet is unlocked; on lock, it is cleared.

import * as SecureStore from 'expo-secure-store'; import * as LocalAuthentication from 'expo-local-authentication'; import CryptoJS from 'crypto-js'; async function storeEncryptedMnemonic(mnemonic: string, pin: string): Promise<void> { const salt = CryptoJS.lib.WordArray.random(128 / 8).toString(); const key = CryptoJS.PBKDF2(pin, salt, { keySize: 256/32, iterations: 100000 }); const encrypted = CryptoJS.AES.encrypt(mnemonic, key.toString()).toString(); await SecureStore.setItemAsync('encrypted_mnemonic', encrypted); await SecureStore.setItemAsync('pbkdf2_salt', salt); } 

Integration with Hardware Wallets

For maximum security, we connect hardware wallets (Ledger, Trezor) via HID/WebUSB. The private key never leaves the device.

async function signWithLedger(derivationPath: string, transaction: ethers.TransactionRequest): Promise<string> { const transport = await TransportWebUSB.create(); const eth = new Eth(transport); const { address } = await eth.getAddress(derivationPath); const unsignedTx = ethers.Transaction.from(transaction); const serialized = ethers.getBytes(unsignedTx.unsignedSerialized); const signature = await eth.signTransaction(derivationPath, Buffer.from(serialized).toString('hex'), null); const signedTx = ethers.Transaction.from({ ...transaction, signature: { r: '0x' + signature.r, s: '0x' + signature.s, v: parseInt(signature.v, 16) } }); return signedTx.serialized; } 

Why Multi-Chain Support Is Critical for a Modern Wallet?

A modern wallet must support multiple networks. For EVM chains (Ethereum, Polygon, Arbitrum, BSC, Avalanche) we use a single key and different RPCs. Non-EVM chains (Solana, Bitcoin, Cosmos) require different cryptographic algorithms. We implement a unified interface for all chains.

We use Multicall3 to fetch token balances in one RPC call for N tokens instead of N calls, speeding up portfolio display by up to 5 times.

Transaction Simulation – Protection from Errors

Before sending a transaction, we show the user what will happen: balance changes, potential revert, or unexpected asset drain. We use Alchemy Simulate Asset Changes or Tenderly Simulation API. If the simulation detects an issue, we warn before real submission. This prevents sending to the wrong address or calling a dangerous contract.

async function simulateTransaction(tx: ethers.TransactionRequest): Promise<SimulationResult> { const response = await fetch(`https://eth-mainnet.g.alchemy.com/v2/${ALCHEMY_KEY}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ id: 1, jsonrpc: '2.0', method: 'alchemy_simulateAssetChanges', params: [{ from: tx.from, to: tx.to, data: tx.data, value: tx.value ? `0x${BigInt(tx.value).toString(16)}` : '0x0' }], }), }); const result = await response.json(); return { willSucceed: !result.result.error, balanceChanges: result.result.changes, gasEstimate: result.result.gasUsed }; } 

WalletConnect v2: Connecting to dApps

We integrate WalletConnect v2 to let users connect their wallet to decentralized applications. We handle session requests: show a modal with dApp details, and after approval, sign transactions.

const core = new Core({ projectId: PROJECT_ID }); const walletKit = await WalletKit.init({ core, metadata: { name: 'My Wallet', ... } }); walletKit.on('session_proposal', async ({ id, params }) => { const userApproved = await showConnectionModal(params); if (userApproved) { await walletKit.approveSession({ id, namespaces: { /* ... */ } }); } }); 

Comparison of Non-Custodial and Custodial Wallets

Characteristic Non-Custodial Custodial
Key control User Service
Risk of breach Low (key on device) High (centralized storage)
Access recovery Via seed phrase Via support
Legal liability Minimal High (regulatory)

Want to give your users full control over their assets? Order a non-custodial wallet development.

Security Checklist

Item Description
Seed storage PBKDF2 + AES-256-GCM, stored in Secure Enclave/Keystore
Memory security Private key only in memory while unlocked
Screen capture Screenshot blocked when displaying seed phrase
Clipboard Cleared 60 seconds after copy
Transaction simulation Warning on revert or drain
Phishing protection Verify dApp URL, warn about unknown contracts
Biometrics Optional biometric unlock
Transport Only HTTPS/WSS, certificate pinning for mobile
Dependency audit npm audit / Snyk on all dependencies

What’s Included in Wallet Development

We deliver: architectural documentation, source code (smart contracts, frontend, backend), API integration (WalletConnect, RPC), UI/UX design, unit and integration testing, security audit, usage instructions, and 30 days of post-launch support.

Technical Stack

Mobile (React Native): React Native + expo-secure-store + ethers.js v6 + viem + WalletConnect SDK + Reown AppKit.

Browser extension: React + WebExtension API + chrome.storage.

Web-based (PWA): Next.js + wagmi + viem + WalletConnect.

Work Process

  1. Architecture decision (1 week): wallet type, chains, platform.
  2. Core development (3-4 weeks): key management, signing, multi-chain.
  3. UI (2-3 weeks): onboarding, portfolio, send/receive, dApp browser.
  4. Security review (1-2 weeks): pen testing key functions.
  5. Testing and launch (1-2 weeks): beta test, mainnet checks.
  6. Full mobile wallet cycle: 3-4 months. Cost is calculated individually based on feature set and platforms.

Get a consultation on wallet architecture. Our experience spans over 10 years in blockchain development; we guarantee security and adherence to best practices.