feat: multi-wallet architecture with localStorage state, EIP-712 verification, cross-tab WS leadership
- 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
This commit is contained in:
80
test/test_wallets.js
Normal file
80
test/test_wallets.js
Normal file
@ -0,0 +1,80 @@
|
||||
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);
|
||||
});
|
||||
Reference in New Issue
Block a user