- wallets.js: WalletManager state management with chain validation - verifier.js: WalletVerifier EIP-712 signing via window.ethereum - stream.js: WalletStreamManager with BroadcastChannel leader election, backoff + jitter - AGENTS.md: updated with coding guidelines
81 lines
3.7 KiB
JavaScript
81 lines
3.7 KiB
JavaScript
import { WalletManager } from '../wallets.js';
|
||
|
||
// 1. Mock localStorage for the Node.js environment
|
||
const mockStorage = {};
|
||
globalThis.localStorage = {
|
||
getItem: (key) => mockStorage[key] || null,
|
||
setItem: (key, value) => { mockStorage[key] = String(value); },
|
||
removeItem: (key) => { delete mockStorage[key]; },
|
||
clear: () => { Object.keys(mockStorage).forEach(k => delete mockStorage[k]); }
|
||
};
|
||
|
||
// Simple test assertion helper
|
||
function assert(condition, message) {
|
||
if (!condition) throw new Error(`❌ FAIL: ${message}`);
|
||
console.log(`✅ PASS: ${message}`);
|
||
}
|
||
|
||
async function runTestSuite() {
|
||
console.log("🚀 Starting WalletManager Test Suite...\n");
|
||
localStorage.clear();
|
||
|
||
const manager = new WalletManager();
|
||
|
||
// --- TEST 1: Address Format Validations ---
|
||
const invalidResult = manager.addWallet("invalid-address", "base", "My EVM");
|
||
assert(!invalidResult.success, "Rejected invalid EVM address format properly");
|
||
|
||
// Add valid addresses across different patterns
|
||
assert(manager.addWallet("0x04f728C520C438A000f7A5E9d904F0e725FFAEFE", "base", "Main Base").success, "Added EVM wallet");
|
||
assert(manager.addWallet("1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa", "bitcoin", "Satoshi BTC").success, "Added Bitcoin wallet");
|
||
assert(manager.addWallet("H7vjR5vP6dfYuxUzoZ76yvBpx6Z3zM7p9qE1vRkWk3xp", "solana", "Solana Trading").success, "Added Solana wallet");
|
||
console.log("👉 ACTUAL WALLETS IN STATE:", manager.getWallets());
|
||
console.log("👉 CURRENT LENGTH:", manager.getWallets().length);
|
||
assert(manager.getWallets().length === 3, "Successfully added 3 distinct multichain wallets");
|
||
|
||
// --- TEST 2: Duplicate Rejection ---
|
||
const dupResult = manager.addWallet("0x04f728C520C438A000f7A5E9d904F0e725FFAEFE", "base", "Duplicate Base");
|
||
assert(!dupResult.success, "Correctly prevented duplicate entry");
|
||
|
||
// --- TEST 3: Verification Flow ---
|
||
const initialWallet = manager.findWallet("0x04f728C520C438A000f7A5E9d904F0e725FFAEFE", "base");
|
||
assert(initialWallet.isVerified === false, "Wallet starts completely unverified");
|
||
|
||
manager.verifyWallet(
|
||
"0x04f728C520C438A000f7A5E9d904F0e725FFAEFE",
|
||
"base",
|
||
"0xmockSignature123456",
|
||
{ action: "Verify Ownership" }
|
||
);
|
||
|
||
const verifiedWallet = manager.findWallet("0x04f728C520C438A000f7A5E9d904F0e725FFAEFE", "base");
|
||
assert(verifiedWallet.isVerified === true, "verifyWallet() successfully flips flag to true");
|
||
assert(verifiedWallet.signature === "0xmockSignature123456", "Signature string is retained");
|
||
|
||
// --- TEST 4: The Core Security Hack Simulation ---
|
||
console.log("\n🕵️♂️ Simulating a user manually tampering with localStorage file...");
|
||
|
||
// Fetch raw storage payload, hack it to true, and write it back
|
||
const rawData = JSON.parse(localStorage.getItem("cbbtc_tracked_wallets"));
|
||
rawData.forEach(w => w.isVerified = true); // Force-inject "true" directly to file
|
||
localStorage.setItem("cbbtc_tracked_wallets", JSON.stringify(rawData));
|
||
|
||
// Instantiate a brand new manager to simulate page reload/reboot
|
||
const maliciousManager = new WalletManager();
|
||
maliciousManager.loadWallets(); // Boot up from hacked storage
|
||
|
||
const postBootWallet = maliciousManager.findWallet("0x04f728C520C438A000f7A5E9d904F0e725FFAEFE", "base");
|
||
assert(postBootWallet.isVerified === false, "SECURITY VERIFIED: Tampered localStorage flags were successfully wiped back to false on boot.");
|
||
|
||
// --- TEST 5: Removal ---
|
||
maliciousManager.removeWallet("1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa", "bitcoin");
|
||
assert(maliciousManager.findWallet("1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa", "bitcoin") === undefined, "Successfully spliced and removed wallet from state");
|
||
|
||
console.log("\n🎉 All core client-side state tests passed successfully!");
|
||
}
|
||
|
||
runTestSuite().catch(err => {
|
||
console.error(err);
|
||
process.exit(1);
|
||
});
|