import { ethers } from 'ethers'; import { Keypair } from '@solana/web3.js'; import bs58 from 'bs58'; import { db } from './db'; import { encrypt, decrypt } from './encryption'; /** * Ensures a merchant has EVM and Solana vault wallets. * Generates them if they don't exist. */ export async function ensureMerchantVaults(merchantId: string) { const result = await db.query( 'SELECT id, evm_vault_address, sol_vault_address FROM merchants WHERE id = $1', [merchantId] ); if (result.rows.length === 0) throw new Error('Merchant not found'); const merchant = result.rows[0]; // If already has vaults, skip if (merchant.evm_vault_address && merchant.sol_vault_address) { return { evm: merchant.evm_vault_address, sol: merchant.sol_vault_address }; } console.log(`[VaultManager] Generating vaults for merchant ${merchantId}...`); // 1. Generate EVM Wallet const evmWallet = ethers.Wallet.createRandom(); const encryptedEvmKey = encrypt(evmWallet.privateKey); // 2. Generate Solana Wallet const solKeypair = Keypair.generate(); const encryptedSolKey = encrypt(bs58.encode(solKeypair.secretKey)); // 3. Save to DB await db.query( `UPDATE merchants SET evm_vault_address = $1, evm_vault_key = $2, sol_vault_address = $3, sol_vault_key = $4 WHERE id = $5`, [ evmWallet.address, encryptedEvmKey, solKeypair.publicKey.toBase58(), encryptedSolKey, merchantId ] ); return { evm: evmWallet.address, sol: solKeypair.publicKey.toBase58() }; } /** * Gets the decrypted private keys for a merchant's vaults. * CRITICAL: Use only when needed (e.g. during manual payout) */ export async function getMerchantVaultSecrets(merchantId: string) { const result = await db.query( 'SELECT evm_vault_key, sol_vault_key FROM merchants WHERE id = $1', [merchantId] ); if (result.rows.length === 0) throw new Error('Merchant not found'); const merchant = result.rows[0]; return { evmKey: merchant.evm_vault_key ? decrypt(merchant.evm_vault_key) : null, solKey: merchant.sol_vault_key ? decrypt(merchant.sol_vault_key) : null }; }