### Chrome Extension Background Message Handler (TypeScript) Source: https://context7.com/boppyorca/omi/llms.txt Routes messages from the popup to the background service worker for various wallet operations. It handles message types like CREATE_WALLET, UNLOCK, LOCK, SIGN_TX, and GET_BALANCE. It returns a Promise resolving to the result of the operation or an error. Usage example shows sending an UNLOCK message. ```typescript // background/messageHandler.ts type MessageType = | 'CREATE_WALLET' | 'IMPORT_WALLET' | 'UNLOCK' | 'LOCK' | 'GET_ACCOUNTS' | 'SIGN_TX' | 'SEND_TX' | 'GET_BALANCE' | 'EXPORT_KEY' | 'EXPORT_MNEMONIC'; interface Message { type: MessageType; payload?: any; } chrome.runtime.onMessage.addListener((message: Message, sender, sendResponse) => { handleMessage(message).then(sendResponse); return true; // Keep channel open for async response }); async function handleMessage(message: Message): Promise { switch (message.type) { case 'CREATE_WALLET': await keyringManager.createNewVault(message.payload.password, message.payload.mnemonic); return { success: true }; case 'UNLOCK': await keyringManager.unlock(message.payload.password); return { success: true, accounts: keyringManager.getAccounts() }; case 'LOCK': keyringManager.lock(); return { success: true }; case 'SIGN_TX': const signedTx = await keyringManager.signTransaction( message.payload.chainType, message.payload.tx, message.payload.accountIndex ); return { success: true, signedTx }; case 'GET_BALANCE': const balance = await getChainBalance(message.payload.address, message.payload.network); return { success: true, balance }; default: return { success: false, error: 'Unknown message type' }; } } // Usage from popup const response = await chrome.runtime.sendMessage({ type: 'UNLOCK', payload: { password: 'myPassword123' } }); console.log(response.accounts); // [{ address: "0x...", ... }] ``` -------------------------------- ### EVM Chain Provider: Interact with EVM Chains using viem Source: https://context7.com/boppyorca/omi/llms.txt Provides functions to interact with EVM-compatible chains using the viem library. It supports creating clients, querying native and ERC-20 token balances, and estimating gas with fee tiers. Dependencies include viem and specific chain definitions. ```typescript import { createPublicClient, http, parseEther, formatEther } from 'viem'; import { mainnet, polygon, arbitrum } from 'viem/chains'; // Create EVM client function createEvmClient(rpcUrl: string, chain: Chain) { return createPublicClient({ chain, transport: http(rpcUrl) }); } // Get native token balance async function getBalance(client: PublicClient, address: `0x${string}`): Promise { return client.getBalance({ address }); } // Get ERC-20 token balance async function getTokenBalance( client: PublicClient, tokenAddress: `0x${string}`, walletAddress: `0x${string}` ): Promise { return client.readContract({ address: tokenAddress, abi: [{ name: 'balanceOf', type: 'function', inputs: [{ type: 'address' }], outputs: [{ type: 'uint256' }] }], functionName: 'balanceOf', args: [walletAddress] }); } // Estimate gas with fee tiers async function estimateGas(client: PublicClient, tx: TransactionRequest) { const [gasLimit, feeData] = await Promise.all([ client.estimateGas(tx), client.estimateFeesPerGas() ]); return { gasLimit, slow: { maxFeePerGas: feeData.maxFeePerGas * 80n / 100n }, average: { maxFeePerGas: feeData.maxFeePerGas }, fast: { maxFeePerGas: feeData.maxFeePerGas * 120n / 100n } }; } // Usage const client = createEvmClient('https://eth.llamarpc.com', mainnet); const balance = await getBalance(client, '0x742d35Cc6634C0532925a3b844Bc9e7595f...'); console.log(formatEther(balance)); // "1.5" ETH const usdcBalance = await getTokenBalance( client, '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC '0x742d35Cc6634C0532925a3b844Bc9e7595f...' ); console.log(usdcBalance); // 1000000000n (1000 USDC with 6 decimals) ``` -------------------------------- ### Zustand Wallet Store for Wallet Operations (TypeScript) Source: https://context7.com/boppyorca/omi/llms.txt Manages wallet state including initialization, lock/unlock status, accounts, and active account index. It provides functions for creating, importing, unlocking, locking, and switching wallets. Dependencies include a keyringManager for cryptographic operations. It returns wallet state and functions to manipulate it. ```typescript import { create } from 'zustand'; interface WalletState { isInitialized: boolean; isLocked: boolean; accounts: Account[]; activeAccountIndex: number; createWallet: (password: string, mnemonic: string) => Promise; importWallet: (password: string, input: string, type: 'seed' | 'privateKey') => Promise; unlock: (password: string) => Promise; lock: () => void; switchAccount: (index: number) => void; } const useWalletStore = create((set, get) => ({ isInitialized: false, isLocked: true, accounts: [], activeAccountIndex: 0, createWallet: async (password, mnemonic) => { await keyringManager.createNewVault(password, mnemonic); const accounts = keyringManager.getAccounts(); set({ isInitialized: true, isLocked: false, accounts }); }, importWallet: async (password, input, type) => { if (type === 'seed') { await keyringManager.createNewVault(password, input); } else { await keyringManager.importPrivateKey(password, input); } const accounts = keyringManager.getAccounts(); set({ isInitialized: true, isLocked: false, accounts }); }, unlock: async (password) => { await keyringManager.unlock(password); const accounts = keyringManager.getAccounts(); set({ isLocked: false, accounts }); }, lock: () => { keyringManager.lock(); set({ isLocked: true, accounts: [] }); }, switchAccount: (index) => set({ activeAccountIndex: index }) })); // Usage in React components function Dashboard() { const { accounts, activeAccountIndex, lock } = useWalletStore(); const activeAccount = accounts[activeAccountIndex]; return (

Address: {activeAccount.address}

); } ``` -------------------------------- ### Define and Use Network Configuration in TypeScript Source: https://context7.com/boppyorca/omi/llms.txt Defines a `NetworkConfig` interface for configuring blockchain networks, including chain ID, RPC URL, and explorer links. It provides a default list of common networks and demonstrates how to add a custom network configuration using a Zustand store. This is useful for managing multi-chain support within the dApp. ```typescript interface NetworkConfig { chainId: string; name: string; rpcUrl: string; symbol: string; explorer: string; type: 'evm' | 'solana'; } const DEFAULT_NETWORKS: NetworkConfig[] = [ { chainId: '1', name: 'Ethereum', rpcUrl: 'https://eth.llamarpc.com', symbol: 'ETH', explorer: 'https://etherscan.io', type: 'evm' }, { chainId: '56', name: 'BNB Chain', rpcUrl: 'https://bsc-dataseed1.binance.org', symbol: 'BNB', explorer: 'https://bscscan.com', type: 'evm' }, { chainId: '137', name: 'Polygon', rpcUrl: 'https://polygon-rpc.com', symbol: 'MATIC', explorer: 'https://polygonscan.com', type: 'evm' }, { chainId: '42161', name: 'Arbitrum', rpcUrl: 'https://arb1.arbitrum.io/rpc', symbol: 'ETH', explorer: 'https://arbiscan.io', type: 'evm' }, { chainId: 'solana', name: 'Solana', rpcUrl: 'https://api.mainnet-beta.solana.com', symbol: 'SOL', explorer: 'https://solscan.io', type: 'solana' } ]; // Add custom network const customNetwork: NetworkConfig = { chainId: '43114', name: 'Avalanche C-Chain', rpcUrl: 'https://api.avax.network/ext/bc/C/rpc', symbol: 'AVAX', explorer: 'https://snowtrace.io', type: 'evm' }; useNetworkStore.getState().addCustomNetwork(customNetwork); ``` -------------------------------- ### Implement EIP-1193 DApp Provider in TypeScript Source: https://context7.com/boppyorca/omi/llms.txt Injects a Web3 provider compliant with EIP-1193 into dApp pages, enabling interaction with Ethereum-compatible blockchains. It uses `window.postMessage` for communication between the injected script and the wallet's background process, supporting standard JSON-RPC methods like `eth_requestAccounts`, `eth_chainId`, and `eth_sendTransaction`. Dependencies include the browser's `window` object for message posting and event listening. ```typescript class OmniWalletProvider { private requestId = 0; async request({ method, params }: { method: string; params?: any[] }): Promise { return new Promise((resolve, reject) => { const id = ++this.requestId; window.postMessage({ type: 'OMNIWALLET_REQUEST', id, method, params }, '*'); const handler = (event: MessageEvent) => { if (event.data.type === 'OMNIWALLET_RESPONSE' && event.data.id === id) { window.removeEventListener('message', handler); if (event.data.error) reject(new Error(event.data.error)); else resolve(event.data.result); } }; window.addEventListener('message', handler); }); } on(event: string, callback: Function) { // Handle accountsChanged, chainChanged, connect, disconnect } } // Inject provider window.ethereum = new OmniWalletProvider(); window.dispatchEvent(new Event('ethereum#initialized')); // dApp usage (from website perspective) const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' }); // Output: ["0x742d35Cc6634C0532925a3b844Bc9e7595f..."] const chainId = await window.ethereum.request({ method: 'eth_chainId' }); // Output: "0x1" (Ethereum mainnet) const txHash = await window.ethereum.request({ method: 'eth_sendTransaction', params: [{ from: accounts[0], to: '0xRecipientAddress...', value: '0x2386f26fc10000', // 0.01 ETH gas: '0x5208' }] }); // Output: "0xTransactionHash..." ``` -------------------------------- ### Derive EVM and Solana Accounts (BIP-44) Source: https://context7.com/boppyorca/omi/llms.txt Derives multiple accounts from a single seed phrase using hierarchical deterministic (HD) derivation according to the BIP-44 standard. It provides specific derivation paths for EVM-compatible chains (`m/44'/60'/0'/0/{index}`) and Solana (`m/44'/501'/0'/0'`). ```typescript import { HDKey } from '@scure/bip32'; import { privateKeyToAccount } from 'viem/accounts'; import { derivePath } from 'ed25519-hd-key'; import nacl from 'tweetnacl'; // Derive EVM account from seed function deriveEVMAccount(seed: Uint8Array, index: number) { const hdKey = HDKey.fromMasterSeed(seed); const derivedKey = hdKey.derive(`m/44'/60'/0'/0/${index}`); const privateKey = `0x${Buffer.from(derivedKey.privateKey!).toString('hex')}`; const account = privateKeyToAccount(privateKey); return { address: account.address, // "0x742d35Cc6634C0532925a3b844Bc9e7595f..." privateKey: privateKey // "0x4c0883a69102937d..." }; } // Derive Solana account from seed function deriveSolanaAccount(seed: Uint8Array, index: number) { const path = `m/44'/501'/${index}'/0'`; const derived = derivePath(path, Buffer.from(seed).toString('hex')); const keypair = nacl.sign.keyPair.fromSeed(derived.key); return { publicKey: Buffer.from(keypair.publicKey).toString('base64'), // Base58 public key secretKey: keypair.secretKey // 64-byte secret key }; } // Usage: Create first account for each chain const seed = mnemonicToSeed("abandon ability able..."); const evmAccount = deriveEVMAccount(seed, 0); const solanaAccount = deriveSolanaAccount(seed, 0); console.log(evmAccount.address); // "0x742d35Cc6634C0532925a3b844Bc9e..." console.log(solanaAccount.publicKey); // "DYw8jCTfwHNRJhhmFcbXvVDTqWMEVFBX6ZKUmG5..." ``` -------------------------------- ### Solana Chain Provider: Interact with Solana Blockchain using @solana/web3.js Source: https://context7.com/boppyorca/omi/llms.txt Enables interaction with the Solana blockchain for SOL and SPL token operations using the @solana/web3.js library. It includes functions for establishing connections, retrieving SOL and SPL token balances, and building/sending SOL transfer transactions. Requires @solana/web3.js and @solana/spl-token. ```typescript import { Connection, PublicKey, LAMPORTS_PER_SOL, Transaction, SystemProgram } from '@solana/web3.js'; import { TOKEN_PROGRAM_ID, getAssociatedTokenAddress } from '@solana/spl-token'; // Create Solana connection function createSolanaConnection(rpcUrl: string): Connection { return new Connection(rpcUrl, 'confirmed'); } // Get SOL balance async function getBalance(connection: Connection, pubkey: PublicKey): Promise { const lamports = await connection.getBalance(pubkey); return lamports / LAMPORTS_PER_SOL; } // Get all SPL token accounts async function getTokenAccounts(connection: Connection, owner: PublicKey) { const accounts = await connection.getParsedTokenAccountsByOwner(owner, { programId: TOKEN_PROGRAM_ID }); return accounts.value.map(acc => ({ mint: acc.account.data.parsed.info.mint, balance: acc.account.data.parsed.info.tokenAmount.uiAmount, decimals: acc.account.data.parsed.info.tokenAmount.decimals })); } // Build and send SOL transfer async function sendSolTransaction( connection: Connection, fromPubkey: PublicKey, toPubkey: PublicKey, lamports: number, signTransaction: (tx: Transaction) => Promise ): Promise { const transaction = new Transaction().add( SystemProgram.transfer({ fromPubkey, toPubkey, lamports }) ); transaction.recentBlockhash = (await connection.getLatestBlockhash()).blockhash; transaction.feePayer = fromPubkey; const signed = await signTransaction(transaction); return connection.sendRawTransaction(signed.serialize()); } // Usage const connection = createSolanaConnection('https://api.mainnet-beta.solana.com'); const pubkey = new PublicKey('DYw8jCTfwHNRJhhmFcbXvVDTqWMEVFBX6ZKUmG5...'); const solBalance = await getBalance(connection, pubkey); console.log(solBalance); // 2.5 SOL const tokens = await getTokenAccounts(connection, pubkey); console.log(tokens); // [{ mint: "EPjFW...", balance: 100, decimals: 6 }, ...] ``` -------------------------------- ### Generate and Validate Mnemonic Phrases (BIP-39) Source: https://context7.com/boppyorca/omi/llms.txt Generates and validates seed phrases using the BIP-39 standard for wallet creation. Supports 12-word (128-bit) and 24-word (256-bit) mnemonics with secure random generation. It also includes functionality to convert mnemonics to seed bytes for key derivation. ```typescript import { generateMnemonic, validateMnemonic, mnemonicToSeed } from 'bip39'; // Generate a new 12-word seed phrase const mnemonic12 = generateMnemonic(128); // Output: "abandon ability able about above absent absorb abstract absurd abuse access accident" // Generate a 24-word seed phrase for higher security const mnemonic24 = generateMnemonic(256); // Output: "abandon ability able about above absent absorb abstract absurd abuse access accident abandon ability able about above absent absorb abstract absurd abuse access accident" // Validate a seed phrase before import const isValid = validateMnemonic("abandon ability able about above absent absorb abstract absurd abuse access accident"); // Output: true const isInvalid = validateMnemonic("invalid seed phrase"); // Output: false // Convert mnemonic to seed bytes for key derivation const seedBytes: Uint8Array = mnemonicToSeed("abandon ability able about above absent absorb abstract absurd abuse access accident"); // Output: Uint8Array(64) - 512-bit seed for HD key derivation ``` -------------------------------- ### KeyringManager for Vault Operations in TypeScript Source: https://context7.com/boppyorca/omi/llms.txt A class that manages wallet vault operations, including creation, locking, unlocking, and account management. It uses the previously defined encryption functions to secure vault data. The class interacts with `chrome.storage.local` for persistence. It supports EVM and Solana account derivation and transaction signing. ```typescript class KeyringManager { private vault: EncryptedPayload | null = null; private decryptedState: VaultState | null = null; // Create new vault with mnemonic async createNewVault(password: string, mnemonic: string): Promise { const salt = crypto.getRandomValues(new Uint8Array(16)); const key = await deriveKey(password, salt); const initialState: VaultState = { mnemonic, accounts: [deriveEVMAccount(mnemonicToSeed(mnemonic), 0)], salt: Array.from(salt) }; this.vault = await encrypt(JSON.stringify(initialState), key); this.decryptedState = initialState; await chrome.storage.local.set({ vault: this.vault }); } // Unlock vault with password async unlock(password: string): Promise { const { vault } = await chrome.storage.local.get('vault'); const key = await deriveKey(password, new Uint8Array(vault.salt)); const decrypted = await decrypt(vault, key); this.decryptedState = JSON.parse(decrypted); } // Lock vault - clear decrypted state from memory lock(): void { this.decryptedState = null; } // Add new derived account addAccount(chainType: 'evm' | 'solana'): Account { if (!this.decryptedState) throw new Error('Vault locked'); const seed = mnemonicToSeed(this.decryptedState.mnemonic); const index = this.decryptedState.accounts.length; const account = chainType === 'evm' ? deriveEVMAccount(seed, index) : deriveSolanaAccount(seed, index); this.decryptedState.accounts.push(account); return account; } // Sign transaction async signTransaction(chainType: 'evm' | 'solana', tx: any, accountIndex: number): Promise { if (!this.decryptedState) throw new Error('Vault locked'); const account = this.decryptedState.accounts[accountIndex]; // Sign with appropriate library (viem for EVM, tweetnacl for Solana) return signedTransaction; } } // Usage const keyring = new KeyringManager(); await keyring.createNewVault('password123', 'abandon ability able...'); const newAccount = keyring.addAccount('evm'); keyring.lock(); ``` -------------------------------- ### Vault Encryption (AES-GCM + PBKDF2) in TypeScript Source: https://context7.com/boppyorca/omi/llms.txt Provides functions to derive an encryption key from a password using PBKDF2, encrypt data using AES-GCM, and decrypt data. It utilizes the Web Crypto API for cryptographic operations. The salt and IV are managed separately. This is crucial for securing sensitive wallet data. ```typescript async function deriveKey(password: string, salt: Uint8Array): Promise { const encoder = new TextEncoder(); const keyMaterial = await crypto.subtle.importKey( 'raw', encoder.encode(password), 'PBKDF2', false, ['deriveBits', 'deriveKey'] ); return crypto.subtle.deriveKey( { name: 'PBKDF2', salt, iterations: 600000, hash: 'SHA-256' }, keyMaterial, { name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt'] ); } // Encrypt vault data async function encrypt(data: string, key: CryptoKey): Promise { const iv = crypto.getRandomValues(new Uint8Array(12)); const encoder = new TextEncoder(); const ciphertext = await crypto.subtle.encrypt( { name: 'AES-GCM', iv }, key, encoder.encode(data) ); return { ciphertext: new Uint8Array(ciphertext), iv }; } // Decrypt vault data async function decrypt(payload: EncryptedPayload, key: CryptoKey): Promise { const decrypted = await crypto.subtle.decrypt( { name: 'AES-GCM', iv: payload.iv }, key, payload.ciphertext ); return new TextDecoder().decode(decrypted); } // Usage const salt = crypto.getRandomValues(new Uint8Array(16)); const key = await deriveKey('MySecurePassword123!', salt); const encrypted = await encrypt('{"mnemonic":"abandon ability...","accounts":[]}', key); const decrypted = await decrypt(encrypted, key); // Output: '{"mnemonic":"abandon ability...","accounts":[]}' ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.