refactor: migrate extension to React and update build configuration
This commit is contained in:
parent
1f2d7e3fec
commit
1e52c572d2
1
Makefile
1
Makefile
@ -30,4 +30,3 @@ build-extension-all: build-wasm-app
|
||||
cp wasm_app/pkg/wasm_app.js extension/public/wasm/wasm_app.js
|
||||
cp wasm_app/pkg/wasm_app_bg.wasm extension/public/wasm/wasm_app_bg.wasm
|
||||
cd extension && npm run build
|
||||
|
||||
|
@ -29,7 +29,7 @@ web-sys = { version = "0.3", features = ["console"] }
|
||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||
getrandom = { version = "0.3", features = ["wasm_js"] }
|
||||
getrandom_02 = { package = "getrandom", version = "0.2.16", features = ["js"] }
|
||||
wasm-bindgen = "0.2"
|
||||
wasm-bindgen = { version = "0.2.92", features = ["serde-serialize"] }
|
||||
js-sys = "0.3"
|
||||
# console_error_panic_hook = "0.1"
|
||||
gloo-net = { version = "0.5", features = ["http"] }
|
||||
|
72
extension/dist/assets/popup.js
vendored
72
extension/dist/assets/popup.js
vendored
File diff suppressed because one or more lines are too long
BIN
extension/dist/assets/wasm_app_bg.wasm
vendored
Normal file
BIN
extension/dist/assets/wasm_app_bg.wasm
vendored
Normal file
Binary file not shown.
6
extension/dist/popup/index.html
vendored
6
extension/dist/popup/index.html
vendored
@ -4,10 +4,12 @@
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>Modular Vault Extension</title>
|
||||
<link rel="stylesheet" href="popup.css">
|
||||
|
||||
<script type="module" crossorigin src="/assets/popup.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script src="popup.js"></script>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
306
extension/dist/popup/popup.js
vendored
306
extension/dist/popup/popup.js
vendored
@ -1,306 +0,0 @@
|
||||
// Simple non-module JavaScript for browser extension popup
|
||||
document.addEventListener('DOMContentLoaded', async function() {
|
||||
const root = document.getElementById('root');
|
||||
root.innerHTML = `
|
||||
<div class="container">
|
||||
<h1>Modular Vault Extension</h1>
|
||||
<div id="status" class="status">Loading WASM module...</div>
|
||||
|
||||
<div id="session-controls">
|
||||
<div id="keyspace-form" class="form-section">
|
||||
<h2>Session</h2>
|
||||
<div class="form-group">
|
||||
<label for="keyspace">Keyspace:</label>
|
||||
<input type="text" id="keyspace" placeholder="Enter keyspace name">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password">Password:</label>
|
||||
<input type="password" id="password" placeholder="Enter password">
|
||||
</div>
|
||||
<div class="button-group">
|
||||
<button id="unlock-btn">Unlock</button>
|
||||
<button id="create-btn">Create New</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="session-info" class="session-info hidden">
|
||||
<h2>Active Session</h2>
|
||||
<p>Current keyspace: <span id="current-keyspace"></span></p>
|
||||
<button id="lock-btn">Lock Session</button>
|
||||
|
||||
<div id="keypair-section" class="form-section">
|
||||
<h2>Keypairs</h2>
|
||||
<button id="create-keypair-btn">Create New Keypair</button>
|
||||
<div id="keypair-list" class="list"></div>
|
||||
</div>
|
||||
|
||||
<div id="sign-section" class="form-section hidden">
|
||||
<h2>Sign Message</h2>
|
||||
<div class="form-group">
|
||||
<label for="message">Message:</label>
|
||||
<textarea id="message" placeholder="Enter message to sign"></textarea>
|
||||
</div>
|
||||
<button id="sign-btn">Sign</button>
|
||||
<div class="form-group">
|
||||
<label for="signature">Signature:</label>
|
||||
<textarea id="signature" readonly></textarea>
|
||||
<button id="copy-btn" class="small">Copy</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// DOM elements
|
||||
const statusEl = document.getElementById('status');
|
||||
const keyspaceFormEl = document.getElementById('keyspace-form');
|
||||
const sessionInfoEl = document.getElementById('session-info');
|
||||
const currentKeyspaceEl = document.getElementById('current-keyspace');
|
||||
const keyspaceInput = document.getElementById('keyspace');
|
||||
const passwordInput = document.getElementById('password');
|
||||
const unlockBtn = document.getElementById('unlock-btn');
|
||||
const createBtn = document.getElementById('create-btn');
|
||||
const lockBtn = document.getElementById('lock-btn');
|
||||
const createKeypairBtn = document.getElementById('create-keypair-btn');
|
||||
const keypairListEl = document.getElementById('keypair-list');
|
||||
const signSectionEl = document.getElementById('sign-section');
|
||||
const messageInput = document.getElementById('message');
|
||||
const signBtn = document.getElementById('sign-btn');
|
||||
const signatureOutput = document.getElementById('signature');
|
||||
const copyBtn = document.getElementById('copy-btn');
|
||||
|
||||
// State
|
||||
let wasmModule = null;
|
||||
let currentKeyspace = null;
|
||||
let keypairs = [];
|
||||
let selectedKeypairId = null;
|
||||
|
||||
// Initialize
|
||||
init();
|
||||
|
||||
async function init() {
|
||||
try {
|
||||
// Get session state from background
|
||||
const sessionState = await getSessionState();
|
||||
|
||||
if (sessionState.currentKeyspace) {
|
||||
// We have an active session
|
||||
currentKeyspace = sessionState.currentKeyspace;
|
||||
keypairs = sessionState.keypairs || [];
|
||||
selectedKeypairId = sessionState.selectedKeypair;
|
||||
|
||||
updateUI();
|
||||
}
|
||||
|
||||
statusEl.textContent = 'Ready';
|
||||
} catch (error) {
|
||||
statusEl.textContent = 'Error: ' + (error.message || 'Unknown error');
|
||||
}
|
||||
}
|
||||
|
||||
function updateUI() {
|
||||
if (currentKeyspace) {
|
||||
// Show session info
|
||||
keyspaceFormEl.classList.add('hidden');
|
||||
sessionInfoEl.classList.remove('hidden');
|
||||
currentKeyspaceEl.textContent = currentKeyspace;
|
||||
|
||||
// Update keypair list
|
||||
updateKeypairList();
|
||||
|
||||
// Show/hide sign section based on selected keypair
|
||||
if (selectedKeypairId) {
|
||||
signSectionEl.classList.remove('hidden');
|
||||
} else {
|
||||
signSectionEl.classList.add('hidden');
|
||||
}
|
||||
} else {
|
||||
// Show keyspace form
|
||||
keyspaceFormEl.classList.remove('hidden');
|
||||
sessionInfoEl.classList.add('hidden');
|
||||
}
|
||||
}
|
||||
|
||||
function updateKeypairList() {
|
||||
// Clear list
|
||||
keypairListEl.innerHTML = '';
|
||||
|
||||
// Add each keypair
|
||||
keypairs.forEach(keypair => {
|
||||
const item = document.createElement('div');
|
||||
item.className = 'list-item' + (selectedKeypairId === keypair.id ? ' selected' : '');
|
||||
item.innerHTML = `
|
||||
<span>${keypair.label || keypair.id}</span>
|
||||
<button class="select-btn" data-id="${keypair.id}">Select</button>
|
||||
`;
|
||||
keypairListEl.appendChild(item);
|
||||
|
||||
// Add select handler
|
||||
item.querySelector('.select-btn').addEventListener('click', async () => {
|
||||
try {
|
||||
statusEl.textContent = 'Selecting keypair...';
|
||||
// Use background service to select keypair for now
|
||||
await chrome.runtime.sendMessage({
|
||||
action: 'update_session',
|
||||
type: 'keypair_selected',
|
||||
data: keypair.id
|
||||
});
|
||||
selectedKeypairId = keypair.id;
|
||||
updateUI();
|
||||
statusEl.textContent = 'Keypair selected: ' + keypair.id;
|
||||
} catch (error) {
|
||||
statusEl.textContent = 'Error selecting keypair: ' + (error.message || 'Unknown error');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Get session state from background
|
||||
async function getSessionState() {
|
||||
return new Promise((resolve) => {
|
||||
chrome.runtime.sendMessage({ action: 'get_session' }, (response) => {
|
||||
resolve(response || { currentKeyspace: null, keypairs: [], selectedKeypair: null });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Event handlers
|
||||
unlockBtn.addEventListener('click', async () => {
|
||||
const keyspace = keyspaceInput.value.trim();
|
||||
const password = passwordInput.value;
|
||||
|
||||
if (!keyspace || !password) {
|
||||
statusEl.textContent = 'Please enter keyspace and password';
|
||||
return;
|
||||
}
|
||||
|
||||
statusEl.textContent = 'Unlocking session...';
|
||||
|
||||
try {
|
||||
// For now, use the background service worker mock
|
||||
await chrome.runtime.sendMessage({
|
||||
action: 'update_session',
|
||||
type: 'keyspace',
|
||||
data: keyspace
|
||||
});
|
||||
|
||||
currentKeyspace = keyspace;
|
||||
updateUI();
|
||||
statusEl.textContent = 'Session unlocked!';
|
||||
|
||||
// Refresh state
|
||||
const state = await getSessionState();
|
||||
keypairs = state.keypairs || [];
|
||||
selectedKeypairId = state.selectedKeypair;
|
||||
updateUI();
|
||||
} catch (error) {
|
||||
statusEl.textContent = 'Error unlocking session: ' + (error.message || 'Unknown error');
|
||||
}
|
||||
});
|
||||
|
||||
createBtn.addEventListener('click', async () => {
|
||||
const keyspace = keyspaceInput.value.trim();
|
||||
const password = passwordInput.value;
|
||||
|
||||
if (!keyspace || !password) {
|
||||
statusEl.textContent = 'Please enter keyspace and password';
|
||||
return;
|
||||
}
|
||||
|
||||
statusEl.textContent = 'Creating keyspace...';
|
||||
|
||||
try {
|
||||
// For now, use the background service worker mock
|
||||
await chrome.runtime.sendMessage({
|
||||
action: 'update_session',
|
||||
type: 'keyspace',
|
||||
data: keyspace
|
||||
});
|
||||
|
||||
currentKeyspace = keyspace;
|
||||
updateUI();
|
||||
statusEl.textContent = 'Keyspace created and unlocked!';
|
||||
} catch (error) {
|
||||
statusEl.textContent = 'Error creating keyspace: ' + (error.message || 'Unknown error');
|
||||
}
|
||||
});
|
||||
|
||||
lockBtn.addEventListener('click', async () => {
|
||||
statusEl.textContent = 'Locking session...';
|
||||
|
||||
try {
|
||||
await chrome.runtime.sendMessage({
|
||||
action: 'update_session',
|
||||
type: 'session_locked'
|
||||
});
|
||||
|
||||
currentKeyspace = null;
|
||||
keypairs = [];
|
||||
selectedKeypairId = null;
|
||||
updateUI();
|
||||
statusEl.textContent = 'Session locked';
|
||||
} catch (error) {
|
||||
statusEl.textContent = 'Error locking session: ' + (error.message || 'Unknown error');
|
||||
}
|
||||
});
|
||||
|
||||
createKeypairBtn.addEventListener('click', async () => {
|
||||
statusEl.textContent = 'Creating keypair...';
|
||||
|
||||
try {
|
||||
// Generate a mock keypair ID
|
||||
const keyId = 'key-' + Date.now().toString(16);
|
||||
const newKeypair = {
|
||||
id: keyId,
|
||||
label: `Secp256k1-Key-${keypairs.length + 1}`
|
||||
};
|
||||
|
||||
await chrome.runtime.sendMessage({
|
||||
action: 'update_session',
|
||||
type: 'keypair_added',
|
||||
data: newKeypair
|
||||
});
|
||||
|
||||
// Refresh state
|
||||
const state = await getSessionState();
|
||||
keypairs = state.keypairs || [];
|
||||
updateUI();
|
||||
|
||||
statusEl.textContent = 'Keypair created: ' + keyId;
|
||||
} catch (error) {
|
||||
statusEl.textContent = 'Error creating keypair: ' + (error.message || 'Unknown error');
|
||||
}
|
||||
});
|
||||
|
||||
signBtn.addEventListener('click', async () => {
|
||||
const message = messageInput.value.trim();
|
||||
|
||||
if (!message) {
|
||||
statusEl.textContent = 'Please enter a message to sign';
|
||||
return;
|
||||
}
|
||||
|
||||
if (!selectedKeypairId) {
|
||||
statusEl.textContent = 'Please select a keypair first';
|
||||
return;
|
||||
}
|
||||
|
||||
statusEl.textContent = 'Signing message...';
|
||||
|
||||
try {
|
||||
// For now, generate a mock signature
|
||||
const mockSignature = Array.from({length: 64}, () => Math.floor(Math.random() * 16).toString(16)).join('');
|
||||
signatureOutput.value = mockSignature;
|
||||
statusEl.textContent = 'Message signed!';
|
||||
} catch (error) {
|
||||
statusEl.textContent = 'Error signing message: ' + (error.message || 'Unknown error');
|
||||
}
|
||||
});
|
||||
|
||||
copyBtn.addEventListener('click', () => {
|
||||
signatureOutput.select();
|
||||
document.execCommand('copy');
|
||||
statusEl.textContent = 'Signature copied to clipboard!';
|
||||
});
|
||||
});
|
BIN
extension/dist/wasm/wasm_app_bg.wasm
vendored
BIN
extension/dist/wasm/wasm_app_bg.wasm
vendored
Binary file not shown.
@ -1,3 +1,5 @@
|
||||
import init, * as wasmModuleImport from '@wasm/wasm_app.js';
|
||||
|
||||
/**
|
||||
* Browser extension-friendly WebAssembly loader and helper functions
|
||||
* This handles loading the WebAssembly module without relying on ES modules
|
||||
@ -21,55 +23,11 @@ export async function loadWasmModule() {
|
||||
if (state.initialized || state.loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
state.loading = true;
|
||||
|
||||
try {
|
||||
// Get paths to WebAssembly files
|
||||
const wasmJsPath = chrome.runtime.getURL('wasm/wasm_app.js');
|
||||
const wasmBinaryPath = chrome.runtime.getURL('wasm/wasm_app_bg.wasm');
|
||||
|
||||
console.log('Loading WASM JS from:', wasmJsPath);
|
||||
console.log('Loading WASM binary from:', wasmBinaryPath);
|
||||
|
||||
// Create a container for our temporary WebAssembly globals
|
||||
window.__wasmApp = {};
|
||||
|
||||
// Create a script element to load the JS file
|
||||
const script = document.createElement('script');
|
||||
script.src = wasmJsPath;
|
||||
|
||||
// Wait for the script to load
|
||||
await new Promise((resolve, reject) => {
|
||||
script.onload = resolve;
|
||||
script.onerror = () => reject(new Error('Failed to load WASM JavaScript file'));
|
||||
document.head.appendChild(script);
|
||||
});
|
||||
|
||||
// Check if the wasm_app global was created
|
||||
if (!window.wasm_app && !window.__wbg_init) {
|
||||
throw new Error('WASM module did not export expected functions');
|
||||
}
|
||||
|
||||
// Get the initialization function
|
||||
const init = window.__wbg_init || (window.wasm_app && window.wasm_app.default);
|
||||
|
||||
if (!init || typeof init !== 'function') {
|
||||
throw new Error('WASM init function not found');
|
||||
}
|
||||
|
||||
// Fetch the WASM binary file
|
||||
const response = await fetch(wasmBinaryPath);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch WASM binary: ${response.status} ${response.statusText}`);
|
||||
}
|
||||
|
||||
// Get the binary data
|
||||
const wasmBinary = await response.arrayBuffer();
|
||||
|
||||
// Initialize the WASM module
|
||||
await init(wasmBinary);
|
||||
|
||||
await init();
|
||||
window.wasm_app = wasmModuleImport;
|
||||
|
||||
// Debug logging for available functions in the WebAssembly module
|
||||
console.log('Available WebAssembly functions:');
|
||||
console.log('init_rhai_env:', typeof window.init_rhai_env, typeof (window.wasm_app && window.wasm_app.init_rhai_env));
|
||||
@ -94,21 +52,19 @@ export async function loadWasmModule() {
|
||||
list_keypairs_debug: window.list_keypairs_debug || (window.wasm_app && window.wasm_app.list_keypairs_debug),
|
||||
check_indexeddb: window.check_indexeddb || (window.wasm_app && window.wasm_app.check_indexeddb)
|
||||
};
|
||||
|
||||
|
||||
// Log what was actually registered
|
||||
console.log('Registered WebAssembly module functions:');
|
||||
for (const [key, value] of Object.entries(wasmModule)) {
|
||||
console.log(`${key}: ${typeof value}`, value ? 'Available' : 'Missing');
|
||||
}
|
||||
|
||||
|
||||
// Initialize the WASM environment
|
||||
if (typeof wasmModule.init_rhai_env === 'function') {
|
||||
wasmModule.init_rhai_env();
|
||||
}
|
||||
|
||||
state.initialized = true;
|
||||
console.log('WASM module loaded and initialized successfully');
|
||||
|
||||
} catch (error) {
|
||||
console.error('Failed to load WASM module:', error);
|
||||
state.error = error.message || 'Unknown error loading WebAssembly module';
|
||||
|
@ -8,6 +8,7 @@
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script src="popup.js"></script>
|
||||
|
||||
<script type="module" src="./main.jsx"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
8
extension/popup/main.jsx
Normal file
8
extension/popup/main.jsx
Normal file
@ -0,0 +1,8 @@
|
||||
import React from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import App from './App';
|
||||
import './style.css';
|
||||
|
||||
// Render the React app
|
||||
const root = createRoot(document.getElementById('root'));
|
||||
root.render(<App />);
|
@ -1,306 +0,0 @@
|
||||
// Simple non-module JavaScript for browser extension popup
|
||||
document.addEventListener('DOMContentLoaded', async function() {
|
||||
const root = document.getElementById('root');
|
||||
root.innerHTML = `
|
||||
<div class="container">
|
||||
<h1>Modular Vault Extension</h1>
|
||||
<div id="status" class="status">Loading WASM module...</div>
|
||||
|
||||
<div id="session-controls">
|
||||
<div id="keyspace-form" class="form-section">
|
||||
<h2>Session</h2>
|
||||
<div class="form-group">
|
||||
<label for="keyspace">Keyspace:</label>
|
||||
<input type="text" id="keyspace" placeholder="Enter keyspace name">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="password">Password:</label>
|
||||
<input type="password" id="password" placeholder="Enter password">
|
||||
</div>
|
||||
<div class="button-group">
|
||||
<button id="unlock-btn">Unlock</button>
|
||||
<button id="create-btn">Create New</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="session-info" class="session-info hidden">
|
||||
<h2>Active Session</h2>
|
||||
<p>Current keyspace: <span id="current-keyspace"></span></p>
|
||||
<button id="lock-btn">Lock Session</button>
|
||||
|
||||
<div id="keypair-section" class="form-section">
|
||||
<h2>Keypairs</h2>
|
||||
<button id="create-keypair-btn">Create New Keypair</button>
|
||||
<div id="keypair-list" class="list"></div>
|
||||
</div>
|
||||
|
||||
<div id="sign-section" class="form-section hidden">
|
||||
<h2>Sign Message</h2>
|
||||
<div class="form-group">
|
||||
<label for="message">Message:</label>
|
||||
<textarea id="message" placeholder="Enter message to sign"></textarea>
|
||||
</div>
|
||||
<button id="sign-btn">Sign</button>
|
||||
<div class="form-group">
|
||||
<label for="signature">Signature:</label>
|
||||
<textarea id="signature" readonly></textarea>
|
||||
<button id="copy-btn" class="small">Copy</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// DOM elements
|
||||
const statusEl = document.getElementById('status');
|
||||
const keyspaceFormEl = document.getElementById('keyspace-form');
|
||||
const sessionInfoEl = document.getElementById('session-info');
|
||||
const currentKeyspaceEl = document.getElementById('current-keyspace');
|
||||
const keyspaceInput = document.getElementById('keyspace');
|
||||
const passwordInput = document.getElementById('password');
|
||||
const unlockBtn = document.getElementById('unlock-btn');
|
||||
const createBtn = document.getElementById('create-btn');
|
||||
const lockBtn = document.getElementById('lock-btn');
|
||||
const createKeypairBtn = document.getElementById('create-keypair-btn');
|
||||
const keypairListEl = document.getElementById('keypair-list');
|
||||
const signSectionEl = document.getElementById('sign-section');
|
||||
const messageInput = document.getElementById('message');
|
||||
const signBtn = document.getElementById('sign-btn');
|
||||
const signatureOutput = document.getElementById('signature');
|
||||
const copyBtn = document.getElementById('copy-btn');
|
||||
|
||||
// State
|
||||
let wasmModule = null;
|
||||
let currentKeyspace = null;
|
||||
let keypairs = [];
|
||||
let selectedKeypairId = null;
|
||||
|
||||
// Initialize
|
||||
init();
|
||||
|
||||
async function init() {
|
||||
try {
|
||||
// Get session state from background
|
||||
const sessionState = await getSessionState();
|
||||
|
||||
if (sessionState.currentKeyspace) {
|
||||
// We have an active session
|
||||
currentKeyspace = sessionState.currentKeyspace;
|
||||
keypairs = sessionState.keypairs || [];
|
||||
selectedKeypairId = sessionState.selectedKeypair;
|
||||
|
||||
updateUI();
|
||||
}
|
||||
|
||||
statusEl.textContent = 'Ready';
|
||||
} catch (error) {
|
||||
statusEl.textContent = 'Error: ' + (error.message || 'Unknown error');
|
||||
}
|
||||
}
|
||||
|
||||
function updateUI() {
|
||||
if (currentKeyspace) {
|
||||
// Show session info
|
||||
keyspaceFormEl.classList.add('hidden');
|
||||
sessionInfoEl.classList.remove('hidden');
|
||||
currentKeyspaceEl.textContent = currentKeyspace;
|
||||
|
||||
// Update keypair list
|
||||
updateKeypairList();
|
||||
|
||||
// Show/hide sign section based on selected keypair
|
||||
if (selectedKeypairId) {
|
||||
signSectionEl.classList.remove('hidden');
|
||||
} else {
|
||||
signSectionEl.classList.add('hidden');
|
||||
}
|
||||
} else {
|
||||
// Show keyspace form
|
||||
keyspaceFormEl.classList.remove('hidden');
|
||||
sessionInfoEl.classList.add('hidden');
|
||||
}
|
||||
}
|
||||
|
||||
function updateKeypairList() {
|
||||
// Clear list
|
||||
keypairListEl.innerHTML = '';
|
||||
|
||||
// Add each keypair
|
||||
keypairs.forEach(keypair => {
|
||||
const item = document.createElement('div');
|
||||
item.className = 'list-item' + (selectedKeypairId === keypair.id ? ' selected' : '');
|
||||
item.innerHTML = `
|
||||
<span>${keypair.label || keypair.id}</span>
|
||||
<button class="select-btn" data-id="${keypair.id}">Select</button>
|
||||
`;
|
||||
keypairListEl.appendChild(item);
|
||||
|
||||
// Add select handler
|
||||
item.querySelector('.select-btn').addEventListener('click', async () => {
|
||||
try {
|
||||
statusEl.textContent = 'Selecting keypair...';
|
||||
// Use background service to select keypair for now
|
||||
await chrome.runtime.sendMessage({
|
||||
action: 'update_session',
|
||||
type: 'keypair_selected',
|
||||
data: keypair.id
|
||||
});
|
||||
selectedKeypairId = keypair.id;
|
||||
updateUI();
|
||||
statusEl.textContent = 'Keypair selected: ' + keypair.id;
|
||||
} catch (error) {
|
||||
statusEl.textContent = 'Error selecting keypair: ' + (error.message || 'Unknown error');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Get session state from background
|
||||
async function getSessionState() {
|
||||
return new Promise((resolve) => {
|
||||
chrome.runtime.sendMessage({ action: 'get_session' }, (response) => {
|
||||
resolve(response || { currentKeyspace: null, keypairs: [], selectedKeypair: null });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// Event handlers
|
||||
unlockBtn.addEventListener('click', async () => {
|
||||
const keyspace = keyspaceInput.value.trim();
|
||||
const password = passwordInput.value;
|
||||
|
||||
if (!keyspace || !password) {
|
||||
statusEl.textContent = 'Please enter keyspace and password';
|
||||
return;
|
||||
}
|
||||
|
||||
statusEl.textContent = 'Unlocking session...';
|
||||
|
||||
try {
|
||||
// For now, use the background service worker mock
|
||||
await chrome.runtime.sendMessage({
|
||||
action: 'update_session',
|
||||
type: 'keyspace',
|
||||
data: keyspace
|
||||
});
|
||||
|
||||
currentKeyspace = keyspace;
|
||||
updateUI();
|
||||
statusEl.textContent = 'Session unlocked!';
|
||||
|
||||
// Refresh state
|
||||
const state = await getSessionState();
|
||||
keypairs = state.keypairs || [];
|
||||
selectedKeypairId = state.selectedKeypair;
|
||||
updateUI();
|
||||
} catch (error) {
|
||||
statusEl.textContent = 'Error unlocking session: ' + (error.message || 'Unknown error');
|
||||
}
|
||||
});
|
||||
|
||||
createBtn.addEventListener('click', async () => {
|
||||
const keyspace = keyspaceInput.value.trim();
|
||||
const password = passwordInput.value;
|
||||
|
||||
if (!keyspace || !password) {
|
||||
statusEl.textContent = 'Please enter keyspace and password';
|
||||
return;
|
||||
}
|
||||
|
||||
statusEl.textContent = 'Creating keyspace...';
|
||||
|
||||
try {
|
||||
// For now, use the background service worker mock
|
||||
await chrome.runtime.sendMessage({
|
||||
action: 'update_session',
|
||||
type: 'keyspace',
|
||||
data: keyspace
|
||||
});
|
||||
|
||||
currentKeyspace = keyspace;
|
||||
updateUI();
|
||||
statusEl.textContent = 'Keyspace created and unlocked!';
|
||||
} catch (error) {
|
||||
statusEl.textContent = 'Error creating keyspace: ' + (error.message || 'Unknown error');
|
||||
}
|
||||
});
|
||||
|
||||
lockBtn.addEventListener('click', async () => {
|
||||
statusEl.textContent = 'Locking session...';
|
||||
|
||||
try {
|
||||
await chrome.runtime.sendMessage({
|
||||
action: 'update_session',
|
||||
type: 'session_locked'
|
||||
});
|
||||
|
||||
currentKeyspace = null;
|
||||
keypairs = [];
|
||||
selectedKeypairId = null;
|
||||
updateUI();
|
||||
statusEl.textContent = 'Session locked';
|
||||
} catch (error) {
|
||||
statusEl.textContent = 'Error locking session: ' + (error.message || 'Unknown error');
|
||||
}
|
||||
});
|
||||
|
||||
createKeypairBtn.addEventListener('click', async () => {
|
||||
statusEl.textContent = 'Creating keypair...';
|
||||
|
||||
try {
|
||||
// Generate a mock keypair ID
|
||||
const keyId = 'key-' + Date.now().toString(16);
|
||||
const newKeypair = {
|
||||
id: keyId,
|
||||
label: `Secp256k1-Key-${keypairs.length + 1}`
|
||||
};
|
||||
|
||||
await chrome.runtime.sendMessage({
|
||||
action: 'update_session',
|
||||
type: 'keypair_added',
|
||||
data: newKeypair
|
||||
});
|
||||
|
||||
// Refresh state
|
||||
const state = await getSessionState();
|
||||
keypairs = state.keypairs || [];
|
||||
updateUI();
|
||||
|
||||
statusEl.textContent = 'Keypair created: ' + keyId;
|
||||
} catch (error) {
|
||||
statusEl.textContent = 'Error creating keypair: ' + (error.message || 'Unknown error');
|
||||
}
|
||||
});
|
||||
|
||||
signBtn.addEventListener('click', async () => {
|
||||
const message = messageInput.value.trim();
|
||||
|
||||
if (!message) {
|
||||
statusEl.textContent = 'Please enter a message to sign';
|
||||
return;
|
||||
}
|
||||
|
||||
if (!selectedKeypairId) {
|
||||
statusEl.textContent = 'Please select a keypair first';
|
||||
return;
|
||||
}
|
||||
|
||||
statusEl.textContent = 'Signing message...';
|
||||
|
||||
try {
|
||||
// For now, generate a mock signature
|
||||
const mockSignature = Array.from({length: 64}, () => Math.floor(Math.random() * 16).toString(16)).join('');
|
||||
signatureOutput.value = mockSignature;
|
||||
statusEl.textContent = 'Message signed!';
|
||||
} catch (error) {
|
||||
statusEl.textContent = 'Error signing message: ' + (error.message || 'Unknown error');
|
||||
}
|
||||
});
|
||||
|
||||
copyBtn.addEventListener('click', () => {
|
||||
signatureOutput.select();
|
||||
document.execCommand('copy');
|
||||
statusEl.textContent = 'Signature copied to clipboard!';
|
||||
});
|
||||
});
|
@ -22,8 +22,8 @@ const copyExtensionFiles = () => {
|
||||
const wasmJsDest = resolve(wasmDistDir, 'wasm_app.js');
|
||||
fs.copyFileSync(wasmJsSource, wasmJsDest);
|
||||
|
||||
// Copy the wasm binary file
|
||||
const wasmBinSource = resolve(__dirname, 'wasm/wasm_app_bg.wasm');
|
||||
// Copy the wasm binary file from the pkg output
|
||||
const wasmBinSource = resolve(__dirname, '../wasm_app/pkg/wasm_app_bg.wasm');
|
||||
const wasmBinDest = resolve(wasmDistDir, 'wasm_app_bg.wasm');
|
||||
fs.copyFileSync(wasmBinSource, wasmBinDest);
|
||||
|
||||
@ -43,16 +43,8 @@ const copyExtensionFiles = () => {
|
||||
fs.mkdirSync(popupDistDir, { recursive: true });
|
||||
}
|
||||
|
||||
// Copy HTML file
|
||||
const htmlSource = resolve(__dirname, 'popup/index.html');
|
||||
const htmlDest = resolve(popupDistDir, 'index.html');
|
||||
fs.copyFileSync(htmlSource, htmlDest);
|
||||
|
||||
// Copy JS file
|
||||
const jsSource = resolve(__dirname, 'popup/popup.js');
|
||||
const jsDest = resolve(popupDistDir, 'popup.js');
|
||||
fs.copyFileSync(jsSource, jsDest);
|
||||
|
||||
|
||||
|
||||
// Copy CSS file
|
||||
const cssSource = resolve(__dirname, 'popup/popup.css');
|
||||
const cssDest = resolve(popupDistDir, 'popup.css');
|
||||
@ -79,12 +71,22 @@ const copyExtensionFiles = () => {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
console.log('Extension files copied to dist directory');
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
import path from 'path';
|
||||
|
||||
export default defineConfig({
|
||||
resolve: {
|
||||
alias: {
|
||||
'@wasm': path.resolve(__dirname, '../wasm_app/pkg')
|
||||
}
|
||||
},
|
||||
|
||||
plugins: [
|
||||
react(),
|
||||
wasm(),
|
||||
|
@ -11,7 +11,7 @@ tokio = { version = "1.37", features = ["rt", "macros"] }
|
||||
async-trait = "0.1"
|
||||
|
||||
getrandom = { version = "0.3", features = ["wasm_js"] }
|
||||
wasm-bindgen = { version = "0.2", features = ["serde-serialize"] }
|
||||
wasm-bindgen = { version = "0.2.92", features = ["serde-serialize"] }
|
||||
wasm-bindgen-futures = "0.4"
|
||||
thiserror = "1"
|
||||
|
||||
@ -27,6 +27,7 @@ getrandom = { version = "0.3", features = ["wasm_js"] }
|
||||
getrandom_02 = { package = "getrandom", version = "0.2.16", features = ["js"] }
|
||||
idb = { version = "0.6" }
|
||||
wasm-bindgen-test = "0.3"
|
||||
wasm-bindgen = { version = "0.2.92", features = ["serde-serialize"] }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
@ -34,6 +34,7 @@ rhai = "1.21.0"
|
||||
|
||||
|
||||
[dev-dependencies]
|
||||
wasm-bindgen = { version = "0.2.92", features = ["serde-serialize"] }
|
||||
wasm-bindgen-test = "0.3"
|
||||
# console_error_panic_hook = "0.1"
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user