Add extension
This commit is contained in:
parent
beba294054
commit
5bc205b2f7
225
crypto_vault_extension/background.js
Normal file
225
crypto_vault_extension/background.js
Normal file
@ -0,0 +1,225 @@
|
||||
let vault = null;
|
||||
let isInitialized = false;
|
||||
let currentSession = null;
|
||||
|
||||
// Utility function to convert Uint8Array to hex
|
||||
function toHex(uint8Array) {
|
||||
return Array.from(uint8Array)
|
||||
.map(b => b.toString(16).padStart(2, '0'))
|
||||
.join('');
|
||||
}
|
||||
|
||||
// Session persistence functions
|
||||
async function saveSession(keyspace) {
|
||||
currentSession = { keyspace, timestamp: Date.now() };
|
||||
await chrome.storage.session.set({ cryptoVaultSession: currentSession });
|
||||
console.log('Session saved:', currentSession);
|
||||
}
|
||||
|
||||
async function loadSession() {
|
||||
try {
|
||||
const result = await chrome.storage.session.get(['cryptoVaultSession']);
|
||||
if (result.cryptoVaultSession) {
|
||||
currentSession = result.cryptoVaultSession;
|
||||
console.log('Session loaded:', currentSession);
|
||||
return currentSession;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Failed to load session:', error);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
async function clearSession() {
|
||||
currentSession = null;
|
||||
await chrome.storage.session.remove(['cryptoVaultSession']);
|
||||
console.log('Session cleared');
|
||||
}
|
||||
|
||||
async function restoreSession() {
|
||||
const session = await loadSession();
|
||||
if (session && vault) {
|
||||
try {
|
||||
// Check if the session is still valid by testing if vault is unlocked
|
||||
const isUnlocked = vault.is_unlocked();
|
||||
if (isUnlocked) {
|
||||
console.log('Session restored successfully for keyspace:', session.keyspace);
|
||||
return session;
|
||||
} else {
|
||||
console.log('Session expired, clearing...');
|
||||
await clearSession();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error checking session validity:', error);
|
||||
await clearSession();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Import WASM module functions
|
||||
import init, {
|
||||
create_keyspace,
|
||||
init_session,
|
||||
is_unlocked,
|
||||
add_keypair,
|
||||
list_keypairs,
|
||||
select_keypair,
|
||||
current_keypair_metadata,
|
||||
current_keypair_public_key,
|
||||
sign,
|
||||
lock_session
|
||||
} from './wasm/wasm_app.js';
|
||||
|
||||
// Initialize WASM module
|
||||
async function initVault() {
|
||||
try {
|
||||
if (vault && isInitialized) return vault;
|
||||
|
||||
// Initialize with the WASM file
|
||||
const wasmUrl = chrome.runtime.getURL('wasm/wasm_app_bg.wasm');
|
||||
await init(wasmUrl);
|
||||
|
||||
// Create a vault object with all the imported functions
|
||||
vault = {
|
||||
create_keyspace,
|
||||
init_session,
|
||||
is_unlocked,
|
||||
add_keypair,
|
||||
list_keypairs,
|
||||
select_keypair,
|
||||
current_keypair_metadata,
|
||||
current_keypair_public_key,
|
||||
sign,
|
||||
lock_session
|
||||
};
|
||||
|
||||
isInitialized = true;
|
||||
console.log('CryptoVault initialized successfully');
|
||||
|
||||
// Try to restore previous session
|
||||
await restoreSession();
|
||||
|
||||
return vault;
|
||||
} catch (error) {
|
||||
console.error('Failed to initialize CryptoVault:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle messages from popup and content scripts
|
||||
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
||||
const handleRequest = async () => {
|
||||
try {
|
||||
if (!vault) {
|
||||
await initVault();
|
||||
}
|
||||
|
||||
switch (request.action) {
|
||||
case 'createKeyspace':
|
||||
await vault.create_keyspace(request.keyspace, request.password);
|
||||
return { success: true };
|
||||
|
||||
case 'initSession':
|
||||
await vault.init_session(request.keyspace, request.password);
|
||||
await saveSession(request.keyspace);
|
||||
return { success: true };
|
||||
|
||||
case 'isUnlocked':
|
||||
const unlocked = vault.is_unlocked();
|
||||
return { success: true, unlocked };
|
||||
|
||||
case 'addKeypair':
|
||||
const result = await vault.add_keypair(request.keyType, request.metadata);
|
||||
return { success: true, result };
|
||||
|
||||
case 'listKeypairs':
|
||||
console.log('Background: listing keypairs...');
|
||||
console.log('Background: vault object:', vault);
|
||||
console.log('Background: vault.list_keypairs function:', vault.list_keypairs);
|
||||
|
||||
// Check if session is unlocked first
|
||||
const isUnlocked = vault.is_unlocked();
|
||||
console.log('Background: is session unlocked?', isUnlocked);
|
||||
|
||||
if (!isUnlocked) {
|
||||
console.log('Background: Session is not unlocked, cannot list keypairs');
|
||||
return { success: false, error: 'Session is not unlocked' };
|
||||
}
|
||||
|
||||
try {
|
||||
const keypairsRaw = await vault.list_keypairs();
|
||||
console.log('Background: keypairs raw result:', keypairsRaw);
|
||||
console.log('Background: keypairs type:', typeof keypairsRaw);
|
||||
|
||||
// Parse JSON string if needed
|
||||
let keypairs;
|
||||
if (typeof keypairsRaw === 'string') {
|
||||
console.log('Background: Parsing JSON string...');
|
||||
keypairs = JSON.parse(keypairsRaw);
|
||||
} else {
|
||||
keypairs = keypairsRaw;
|
||||
}
|
||||
|
||||
console.log('Background: parsed keypairs:', keypairs);
|
||||
console.log('Background: parsed keypairs type:', typeof keypairs);
|
||||
console.log('Background: keypairs array length:', Array.isArray(keypairs) ? keypairs.length : 'not an array');
|
||||
|
||||
return { success: true, keypairs };
|
||||
} catch (listError) {
|
||||
console.error('Background: Error calling list_keypairs:', listError);
|
||||
throw listError;
|
||||
}
|
||||
|
||||
case 'selectKeypair':
|
||||
vault.select_keypair(request.keyId);
|
||||
return { success: true };
|
||||
|
||||
case 'getCurrentKeypairMetadata':
|
||||
const metadata = vault.current_keypair_metadata();
|
||||
return { success: true, metadata };
|
||||
|
||||
case 'getCurrentKeypairPublicKey':
|
||||
const publicKey = vault.current_keypair_public_key();
|
||||
const hexKey = toHex(publicKey);
|
||||
return { success: true, publicKey: hexKey };
|
||||
|
||||
case 'sign':
|
||||
const signature = await vault.sign(new Uint8Array(request.message));
|
||||
return { success: true, signature };
|
||||
|
||||
case 'lockSession':
|
||||
vault.lock_session();
|
||||
await clearSession();
|
||||
return { success: true };
|
||||
|
||||
case 'getStatus':
|
||||
const status = vault ? vault.is_unlocked() : false;
|
||||
const session = await loadSession();
|
||||
return {
|
||||
success: true,
|
||||
status,
|
||||
session: session ? { keyspace: session.keyspace } : null
|
||||
};
|
||||
|
||||
default:
|
||||
throw new Error('Unknown action: ' + request.action);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Background script error:', error);
|
||||
return { success: false, error: error.message };
|
||||
}
|
||||
};
|
||||
|
||||
handleRequest().then(sendResponse);
|
||||
return true; // Keep the message channel open for async response
|
||||
});
|
||||
|
||||
// Initialize vault when extension starts
|
||||
chrome.runtime.onStartup.addListener(() => {
|
||||
initVault();
|
||||
});
|
||||
|
||||
chrome.runtime.onInstalled.addListener(() => {
|
||||
initVault();
|
||||
});
|
89
crypto_vault_extension/content.js
Normal file
89
crypto_vault_extension/content.js
Normal file
@ -0,0 +1,89 @@
|
||||
// Content script for potential webpage integration
|
||||
// This can be used to inject CryptoVault functionality into webpages
|
||||
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
// Create a bridge between webpage and extension
|
||||
const cryptoVaultBridge = {
|
||||
async isAvailable() {
|
||||
try {
|
||||
const response = await chrome.runtime.sendMessage({ action: 'getStatus' });
|
||||
return response.success && response.status;
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
async sign(message) {
|
||||
try {
|
||||
const response = await chrome.runtime.sendMessage({
|
||||
action: 'sign',
|
||||
message: Array.from(new TextEncoder().encode(message))
|
||||
});
|
||||
return response.success ? response.signature : null;
|
||||
} catch (error) {
|
||||
console.error('CryptoVault sign error:', error);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
async getPublicKey() {
|
||||
try {
|
||||
const response = await chrome.runtime.sendMessage({ action: 'getCurrentKeypairPublicKey' });
|
||||
return response.success ? response.publicKey : null;
|
||||
} catch (error) {
|
||||
console.error('CryptoVault getPublicKey error:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Expose to window for webpage access (optional)
|
||||
if (window.location.protocol === 'https:' || window.location.hostname === 'localhost') {
|
||||
window.cryptoVault = cryptoVaultBridge;
|
||||
|
||||
// Dispatch event to let webpage know CryptoVault is available
|
||||
window.dispatchEvent(new CustomEvent('cryptovault-ready', {
|
||||
detail: { available: true }
|
||||
}));
|
||||
}
|
||||
|
||||
// Listen for messages from webpage
|
||||
window.addEventListener('message', async (event) => {
|
||||
if (event.source !== window || !event.data.cryptoVault) return;
|
||||
|
||||
const { action, id, data } = event.data;
|
||||
let result;
|
||||
|
||||
try {
|
||||
switch (action) {
|
||||
case 'sign':
|
||||
result = await cryptoVaultBridge.sign(data.message);
|
||||
break;
|
||||
case 'getPublicKey':
|
||||
result = await cryptoVaultBridge.getPublicKey();
|
||||
break;
|
||||
case 'isAvailable':
|
||||
result = await cryptoVaultBridge.isAvailable();
|
||||
break;
|
||||
default:
|
||||
throw new Error('Unknown action: ' + action);
|
||||
}
|
||||
|
||||
window.postMessage({
|
||||
cryptoVaultResponse: true,
|
||||
id,
|
||||
success: true,
|
||||
result
|
||||
}, '*');
|
||||
} catch (error) {
|
||||
window.postMessage({
|
||||
cryptoVaultResponse: true,
|
||||
id,
|
||||
success: false,
|
||||
error: error.message
|
||||
}, '*');
|
||||
}
|
||||
});
|
||||
})();
|
BIN
crypto_vault_extension/icons/icon128.png
Normal file
BIN
crypto_vault_extension/icons/icon128.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.9 KiB |
BIN
crypto_vault_extension/icons/icon16.png
Normal file
BIN
crypto_vault_extension/icons/icon16.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 454 B |
BIN
crypto_vault_extension/icons/icon32.png
Normal file
BIN
crypto_vault_extension/icons/icon32.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 712 B |
BIN
crypto_vault_extension/icons/icon48.png
Normal file
BIN
crypto_vault_extension/icons/icon48.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.1 KiB |
46
crypto_vault_extension/manifest.json
Normal file
46
crypto_vault_extension/manifest.json
Normal file
@ -0,0 +1,46 @@
|
||||
{
|
||||
"manifest_version": 3,
|
||||
"name": "CryptoVault",
|
||||
"version": "1.0.0",
|
||||
"description": "Secure cryptographic key management and signing in your browser",
|
||||
|
||||
"permissions": [
|
||||
"storage",
|
||||
"activeTab"
|
||||
],
|
||||
|
||||
"background": {
|
||||
"service_worker": "background.js",
|
||||
"type": "module"
|
||||
},
|
||||
|
||||
"content_scripts": [
|
||||
{
|
||||
"matches": ["<all_urls>"],
|
||||
"js": ["content.js"]
|
||||
}
|
||||
],
|
||||
|
||||
"action": {
|
||||
"default_popup": "popup.html",
|
||||
"default_icon": {
|
||||
"16": "icons/icon16.png",
|
||||
"48": "icons/icon48.png",
|
||||
"128": "icons/icon128.png"
|
||||
}
|
||||
},
|
||||
|
||||
"web_accessible_resources": [
|
||||
{
|
||||
"resources": [
|
||||
"wasm/*.wasm",
|
||||
"wasm/*.js"
|
||||
],
|
||||
"matches": ["<all_urls>"]
|
||||
}
|
||||
],
|
||||
|
||||
"content_security_policy": {
|
||||
"extension_pages": "script-src 'self' 'wasm-unsafe-eval'; object-src 'self'; style-src 'self' 'unsafe-inline';"
|
||||
}
|
||||
}
|
138
crypto_vault_extension/popup.html
Normal file
138
crypto_vault_extension/popup.html
Normal file
@ -0,0 +1,138 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<link rel="stylesheet" href="styles/popup.css">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<header class="header">
|
||||
<div class="logo">
|
||||
<div class="logo-icon">🔐</div>
|
||||
<h1>CryptoVault</h1>
|
||||
</div>
|
||||
<div class="status-indicator" id="statusIndicator">
|
||||
<div class="status-dot"></div>
|
||||
<span id="statusText">Initializing...</span>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Create/Login Section -->
|
||||
<section class="section" id="authSection">
|
||||
<div class="card">
|
||||
<h2>Access Your Vault</h2>
|
||||
<div class="form-group">
|
||||
<label for="keyspaceInput">Keyspace Name</label>
|
||||
<input type="text" id="keyspaceInput" placeholder="Enter keyspace name">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="passwordInput">Password</label>
|
||||
<input type="password" id="passwordInput" placeholder="Enter password">
|
||||
</div>
|
||||
<div class="button-group">
|
||||
<button id="createKeyspaceBtn" class="btn btn-secondary">Create New</button>
|
||||
<button id="loginBtn" class="btn btn-primary">Unlock</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Main Vault Section -->
|
||||
<section class="section hidden" id="vaultSection">
|
||||
<div class="vault-header">
|
||||
<h2>Your Keypairs</h2>
|
||||
<button id="lockBtn" class="btn btn-ghost">🔒 Lock</button>
|
||||
</div>
|
||||
|
||||
<!-- Add Keypair Toggle Button -->
|
||||
<div class="add-keypair-toggle">
|
||||
<button id="toggleAddKeypairBtn" class="btn btn-primary">
|
||||
<span class="btn-icon">+</span>
|
||||
Add Keypair
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Add Keypair Form (Hidden by default) -->
|
||||
<div class="card add-keypair-form hidden" id="addKeypairCard">
|
||||
<div class="form-header">
|
||||
<h3>Add New Keypair</h3>
|
||||
<button id="cancelAddKeypairBtn" class="btn-close" title="Close">×</button>
|
||||
</div>
|
||||
<div class="form-content">
|
||||
<div class="form-group">
|
||||
<label for="keyTypeSelect">Key Type</label>
|
||||
<select id="keyTypeSelect" class="select">
|
||||
<option value="Secp256k1">Secp256k1</option>
|
||||
<option value="Ed25519">Ed25519</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="keyNameInput">Keypair Name</label>
|
||||
<input type="text" id="keyNameInput" placeholder="Enter a name for your keypair">
|
||||
</div>
|
||||
<div class="form-actions">
|
||||
<button id="addKeypairBtn" class="btn btn-primary">Create Keypair</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Keypairs List -->
|
||||
<div class="card">
|
||||
<h3>Keypairs</h3>
|
||||
<div id="keypairsList" class="keypairs-list">
|
||||
<div class="loading">Loading keypairs...</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Selected Keypair Info - Hidden from user -->
|
||||
<div class="card hidden completely-hidden" id="selectedKeypairCard">
|
||||
<h3>Selected Keypair</h3>
|
||||
<div class="keypair-info">
|
||||
<div class="info-row">
|
||||
<label>Name:</label>
|
||||
<span id="selectedName">-</span>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<label>Type:</label>
|
||||
<span id="selectedType">-</span>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<label>Public Key:</label>
|
||||
<div class="public-key-container">
|
||||
<code id="selectedPublicKey">-</code>
|
||||
<button id="copyPublicKeyBtn" class="btn-copy" title="Copy to clipboard">📋</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Sign Message -->
|
||||
<div class="card">
|
||||
<h3>Sign Message</h3>
|
||||
<div class="form-group">
|
||||
<label for="messageInput">Message (hex or text)</label>
|
||||
<textarea id="messageInput" placeholder="Enter message to sign" rows="3"></textarea>
|
||||
</div>
|
||||
<button id="signBtn" class="btn btn-primary" disabled>Sign Message</button>
|
||||
<div id="signatureResult" class="signature-result hidden">
|
||||
<label>Signature:</label>
|
||||
<div class="signature-container">
|
||||
<code id="signatureValue"></code>
|
||||
<button id="copySignatureBtn" class="btn-copy" title="Copy to clipboard">📋</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Loading Overlay -->
|
||||
<div class="loading-overlay hidden" id="loadingOverlay">
|
||||
<div class="spinner"></div>
|
||||
<p>Processing...</p>
|
||||
</div>
|
||||
|
||||
<!-- Toast Notifications -->
|
||||
<div id="toast" class="toast hidden"></div>
|
||||
</div>
|
||||
|
||||
<script src="popup.js"></script>
|
||||
</body>
|
||||
</html>
|
648
crypto_vault_extension/popup.js
Normal file
648
crypto_vault_extension/popup.js
Normal file
@ -0,0 +1,648 @@
|
||||
// Utility functions
|
||||
function showToast(message, type = 'info') {
|
||||
const toast = document.getElementById('toast');
|
||||
toast.textContent = message;
|
||||
toast.className = `toast ${type}`;
|
||||
setTimeout(() => toast.classList.add('hidden'), 3000);
|
||||
}
|
||||
|
||||
function showLoading(show = true) {
|
||||
const overlay = document.getElementById('loadingOverlay');
|
||||
overlay.classList.toggle('hidden', !show);
|
||||
}
|
||||
|
||||
// Enhanced loading states for buttons
|
||||
function setButtonLoading(button, loading = true, originalText = null) {
|
||||
if (loading) {
|
||||
button.dataset.originalText = button.textContent;
|
||||
button.classList.add('loading');
|
||||
button.disabled = true;
|
||||
} else {
|
||||
button.classList.remove('loading');
|
||||
button.disabled = false;
|
||||
if (originalText) {
|
||||
button.textContent = originalText;
|
||||
} else if (button.dataset.originalText) {
|
||||
button.textContent = button.dataset.originalText;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Show inline loading for specific operations
|
||||
function showInlineLoading(element, message = 'Processing...') {
|
||||
element.innerHTML = `
|
||||
<div class="inline-loading">
|
||||
<div class="inline-spinner"></div>
|
||||
<span>${message}</span>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
// Enhanced error handling utility
|
||||
function getErrorMessage(error, fallback = 'An unexpected error occurred') {
|
||||
if (!error) return fallback;
|
||||
|
||||
// If it's a string, return it
|
||||
if (typeof error === 'string') {
|
||||
return error.trim() || fallback;
|
||||
}
|
||||
|
||||
// If it's an Error object
|
||||
if (error instanceof Error) {
|
||||
return error.message || fallback;
|
||||
}
|
||||
|
||||
// If it's an object with error property
|
||||
if (error.error) {
|
||||
return getErrorMessage(error.error, fallback);
|
||||
}
|
||||
|
||||
// If it's an object with message property
|
||||
if (error.message) {
|
||||
return error.message || fallback;
|
||||
}
|
||||
|
||||
// Try to stringify if it's an object
|
||||
if (typeof error === 'object') {
|
||||
try {
|
||||
const stringified = JSON.stringify(error);
|
||||
if (stringified && stringified !== '{}') {
|
||||
return stringified;
|
||||
}
|
||||
} catch (e) {
|
||||
// Ignore JSON stringify errors
|
||||
}
|
||||
}
|
||||
|
||||
return fallback;
|
||||
}
|
||||
|
||||
// Enhanced response error handling
|
||||
function getResponseError(response, operation = 'operation') {
|
||||
if (!response) {
|
||||
return `Failed to ${operation}: No response received`;
|
||||
}
|
||||
|
||||
if (response.success === false || response.error) {
|
||||
const errorMsg = getErrorMessage(response.error, `${operation} failed`);
|
||||
|
||||
// Handle specific error types
|
||||
if (errorMsg.includes('decryption error') || errorMsg.includes('aead::Error')) {
|
||||
return 'Invalid password or corrupted keyspace data';
|
||||
}
|
||||
|
||||
if (errorMsg.includes('Crypto error')) {
|
||||
return 'Keyspace not found or corrupted. Try creating a new one.';
|
||||
}
|
||||
|
||||
if (errorMsg.includes('not unlocked') || errorMsg.includes('session')) {
|
||||
return 'Session expired. Please login again.';
|
||||
}
|
||||
|
||||
return errorMsg;
|
||||
}
|
||||
|
||||
return `Failed to ${operation}: Unknown error`;
|
||||
}
|
||||
|
||||
function showSection(sectionId) {
|
||||
document.querySelectorAll('.section').forEach(s => s.classList.add('hidden'));
|
||||
document.getElementById(sectionId).classList.remove('hidden');
|
||||
}
|
||||
|
||||
function setStatus(text, isConnected = false) {
|
||||
document.getElementById('statusText').textContent = text;
|
||||
const indicator = document.getElementById('statusIndicator');
|
||||
indicator.classList.toggle('connected', isConnected);
|
||||
}
|
||||
|
||||
// Message handling
|
||||
async function sendMessage(action, data = {}) {
|
||||
return new Promise((resolve) => {
|
||||
chrome.runtime.sendMessage({ action, ...data }, resolve);
|
||||
});
|
||||
}
|
||||
|
||||
// Copy to clipboard
|
||||
async function copyToClipboard(text) {
|
||||
try {
|
||||
await navigator.clipboard.writeText(text);
|
||||
showToast('Copied to clipboard!', 'success');
|
||||
} catch (err) {
|
||||
showToast('Failed to copy', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
// Convert string to Uint8Array
|
||||
function stringToUint8Array(str) {
|
||||
if (str.match(/^[0-9a-fA-F]+$/)) {
|
||||
// Hex string
|
||||
const bytes = [];
|
||||
for (let i = 0; i < str.length; i += 2) {
|
||||
bytes.push(parseInt(str.substr(i, 2), 16));
|
||||
}
|
||||
return bytes;
|
||||
} else {
|
||||
// Regular string
|
||||
return Array.from(new TextEncoder().encode(str));
|
||||
}
|
||||
}
|
||||
|
||||
// DOM Elements
|
||||
const elements = {
|
||||
keyspaceInput: document.getElementById('keyspaceInput'),
|
||||
passwordInput: document.getElementById('passwordInput'),
|
||||
createKeyspaceBtn: document.getElementById('createKeyspaceBtn'),
|
||||
loginBtn: document.getElementById('loginBtn'),
|
||||
lockBtn: document.getElementById('lockBtn'),
|
||||
toggleAddKeypairBtn: document.getElementById('toggleAddKeypairBtn'),
|
||||
addKeypairCard: document.getElementById('addKeypairCard'),
|
||||
keyTypeSelect: document.getElementById('keyTypeSelect'),
|
||||
keyNameInput: document.getElementById('keyNameInput'),
|
||||
addKeypairBtn: document.getElementById('addKeypairBtn'),
|
||||
cancelAddKeypairBtn: document.getElementById('cancelAddKeypairBtn'),
|
||||
keypairsList: document.getElementById('keypairsList'),
|
||||
selectedKeypairCard: document.getElementById('selectedKeypairCard'),
|
||||
messageInput: document.getElementById('messageInput'),
|
||||
signBtn: document.getElementById('signBtn'),
|
||||
signatureResult: document.getElementById('signatureResult'),
|
||||
copyPublicKeyBtn: document.getElementById('copyPublicKeyBtn'),
|
||||
copySignatureBtn: document.getElementById('copySignatureBtn'),
|
||||
};
|
||||
|
||||
let currentKeyspace = null;
|
||||
let selectedKeypairId = null;
|
||||
|
||||
// Initialize
|
||||
document.addEventListener('DOMContentLoaded', async function() {
|
||||
setStatus('Initializing...', false);
|
||||
|
||||
// Event listeners
|
||||
elements.createKeyspaceBtn.addEventListener('click', createKeyspace);
|
||||
elements.loginBtn.addEventListener('click', login);
|
||||
elements.lockBtn.addEventListener('click', lockSession);
|
||||
elements.toggleAddKeypairBtn.addEventListener('click', toggleAddKeypairForm);
|
||||
elements.addKeypairBtn.addEventListener('click', addKeypair);
|
||||
elements.cancelAddKeypairBtn.addEventListener('click', hideAddKeypairForm);
|
||||
elements.signBtn.addEventListener('click', signMessage);
|
||||
elements.copyPublicKeyBtn.addEventListener('click', () => {
|
||||
const publicKey = document.getElementById('selectedPublicKey').textContent;
|
||||
copyToClipboard(publicKey);
|
||||
});
|
||||
elements.copySignatureBtn.addEventListener('click', () => {
|
||||
const signature = document.getElementById('signatureValue').textContent;
|
||||
copyToClipboard(signature);
|
||||
});
|
||||
|
||||
// Enable sign button when message is entered
|
||||
elements.messageInput.addEventListener('input', () => {
|
||||
elements.signBtn.disabled = !elements.messageInput.value.trim() || !selectedKeypairId;
|
||||
});
|
||||
|
||||
// Keyboard shortcuts
|
||||
document.addEventListener('keydown', (e) => {
|
||||
// Escape key closes the add keypair form
|
||||
if (e.key === 'Escape' && !elements.addKeypairCard.classList.contains('hidden')) {
|
||||
hideAddKeypairForm();
|
||||
}
|
||||
// Enter key in the name input submits the form
|
||||
if (e.key === 'Enter' && e.target === elements.keyNameInput) {
|
||||
e.preventDefault();
|
||||
if (elements.keyNameInput.value.trim()) {
|
||||
addKeypair();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Check for existing session
|
||||
await checkExistingSession();
|
||||
});
|
||||
|
||||
async function checkExistingSession() {
|
||||
try {
|
||||
const response = await sendMessage('getStatus');
|
||||
if (response && response.success && response.status && response.session) {
|
||||
// Session is active
|
||||
currentKeyspace = response.session.keyspace;
|
||||
elements.keyspaceInput.value = currentKeyspace;
|
||||
setStatus(`Connected to ${currentKeyspace}`, true);
|
||||
showSection('vaultSection');
|
||||
await loadKeypairs();
|
||||
showToast('Session restored!', 'success');
|
||||
} else {
|
||||
// No active session
|
||||
setStatus('Ready', true);
|
||||
showSection('authSection');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error checking session:', error);
|
||||
setStatus('Ready', true);
|
||||
showSection('authSection');
|
||||
// Don't show toast for session check errors as it's not user-initiated
|
||||
}
|
||||
}
|
||||
|
||||
// Toggle add keypair form
|
||||
function toggleAddKeypairForm() {
|
||||
const isHidden = elements.addKeypairCard.classList.contains('hidden');
|
||||
if (isHidden) {
|
||||
showAddKeypairForm();
|
||||
} else {
|
||||
hideAddKeypairForm();
|
||||
}
|
||||
}
|
||||
|
||||
function showAddKeypairForm() {
|
||||
elements.addKeypairCard.classList.remove('hidden');
|
||||
|
||||
// Rotate the + icon to × when form is open
|
||||
const icon = elements.toggleAddKeypairBtn.querySelector('.btn-icon');
|
||||
icon.style.transform = 'rotate(45deg)';
|
||||
|
||||
// Focus on the name input after animation
|
||||
setTimeout(() => {
|
||||
elements.keyNameInput.focus();
|
||||
}, 300);
|
||||
}
|
||||
|
||||
function hideAddKeypairForm() {
|
||||
elements.addKeypairCard.classList.add('hidden');
|
||||
|
||||
// Rotate the icon back to +
|
||||
const icon = elements.toggleAddKeypairBtn.querySelector('.btn-icon');
|
||||
icon.style.transform = 'rotate(0deg)';
|
||||
|
||||
// Clear the form
|
||||
elements.keyNameInput.value = '';
|
||||
elements.keyTypeSelect.selectedIndex = 0;
|
||||
}
|
||||
|
||||
// Clear all vault-related state and UI
|
||||
function clearVaultState() {
|
||||
// Clear message input and signature result
|
||||
elements.messageInput.value = '';
|
||||
elements.signatureResult.classList.add('hidden');
|
||||
document.getElementById('signatureValue').textContent = '';
|
||||
|
||||
// Clear selected keypair state
|
||||
selectedKeypairId = null;
|
||||
elements.signBtn.disabled = true;
|
||||
|
||||
// Clear selected keypair info (hidden elements)
|
||||
document.getElementById('selectedName').textContent = '-';
|
||||
document.getElementById('selectedType').textContent = '-';
|
||||
document.getElementById('selectedPublicKey').textContent = '-';
|
||||
|
||||
// Hide add keypair form if open
|
||||
hideAddKeypairForm();
|
||||
|
||||
// Clear keypairs list
|
||||
elements.keypairsList.innerHTML = '<div class="loading">Loading keypairs...</div>';
|
||||
}
|
||||
|
||||
async function createKeyspace() {
|
||||
const keyspace = elements.keyspaceInput.value.trim();
|
||||
const password = elements.passwordInput.value.trim();
|
||||
|
||||
if (!keyspace || !password) {
|
||||
showToast('Please enter keyspace name and password', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
setButtonLoading(elements.createKeyspaceBtn, true);
|
||||
try {
|
||||
const response = await sendMessage('createKeyspace', { keyspace, password });
|
||||
if (response && response.success) {
|
||||
showToast('Keyspace created successfully!', 'success');
|
||||
// Clear any existing state before auto-login
|
||||
clearVaultState();
|
||||
await login(); // Auto-login after creation
|
||||
} else {
|
||||
const errorMsg = getResponseError(response, 'create keyspace');
|
||||
showToast(errorMsg, 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
const errorMsg = getErrorMessage(error, 'Failed to create keyspace');
|
||||
console.error('Create keyspace error:', error);
|
||||
showToast(errorMsg, 'error');
|
||||
} finally {
|
||||
setButtonLoading(elements.createKeyspaceBtn, false);
|
||||
}
|
||||
}
|
||||
|
||||
async function login() {
|
||||
const keyspace = elements.keyspaceInput.value.trim();
|
||||
const password = elements.passwordInput.value.trim();
|
||||
|
||||
if (!keyspace || !password) {
|
||||
showToast('Please enter keyspace name and password', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
setButtonLoading(elements.loginBtn, true);
|
||||
try {
|
||||
const response = await sendMessage('initSession', { keyspace, password });
|
||||
if (response && response.success) {
|
||||
currentKeyspace = keyspace;
|
||||
setStatus(`Connected to ${keyspace}`, true);
|
||||
showSection('vaultSection');
|
||||
|
||||
// Clear any previous vault state before loading new keyspace
|
||||
clearVaultState();
|
||||
await loadKeypairs();
|
||||
|
||||
showToast('Logged in successfully!', 'success');
|
||||
} else {
|
||||
const errorMsg = getResponseError(response, 'login');
|
||||
showToast(errorMsg, 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
const errorMsg = getErrorMessage(error, 'Failed to login');
|
||||
console.error('Login error:', error);
|
||||
showToast(errorMsg, 'error');
|
||||
} finally {
|
||||
setButtonLoading(elements.loginBtn, false);
|
||||
}
|
||||
}
|
||||
|
||||
async function lockSession() {
|
||||
showLoading(true);
|
||||
try {
|
||||
await sendMessage('lockSession');
|
||||
currentKeyspace = null;
|
||||
selectedKeypairId = null;
|
||||
setStatus('Locked', false);
|
||||
showSection('authSection');
|
||||
|
||||
// Clear all form inputs
|
||||
elements.keyspaceInput.value = '';
|
||||
elements.passwordInput.value = '';
|
||||
clearVaultState();
|
||||
|
||||
showToast('Session locked', 'info');
|
||||
} catch (error) {
|
||||
showToast('Error: ' + error.message, 'error');
|
||||
} finally {
|
||||
showLoading(false);
|
||||
}
|
||||
}
|
||||
|
||||
async function addKeypair() {
|
||||
const keyType = elements.keyTypeSelect.value;
|
||||
const keyName = elements.keyNameInput.value.trim();
|
||||
|
||||
if (!keyName) {
|
||||
showToast('Please enter a name for the keypair', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
// Use button loading instead of full overlay
|
||||
setButtonLoading(elements.addKeypairBtn, true);
|
||||
|
||||
try {
|
||||
console.log('Adding keypair:', { keyType, keyName });
|
||||
const metadata = JSON.stringify({ name: keyName });
|
||||
console.log('Metadata:', metadata);
|
||||
|
||||
const response = await sendMessage('addKeypair', { keyType, metadata });
|
||||
console.log('Add keypair response:', response);
|
||||
|
||||
if (response && response.success) {
|
||||
console.log('Keypair added successfully, clearing input and reloading list...');
|
||||
hideAddKeypairForm(); // Hide the form after successful addition
|
||||
|
||||
// Show inline loading in keypairs list while reloading
|
||||
showInlineLoading(elements.keypairsList, 'Adding keypair...');
|
||||
await loadKeypairs();
|
||||
|
||||
showToast('Keypair added successfully!', 'success');
|
||||
} else {
|
||||
const errorMsg = getResponseError(response, 'add keypair');
|
||||
console.error('Failed to add keypair:', response);
|
||||
showToast(errorMsg, 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
const errorMsg = getErrorMessage(error, 'Failed to add keypair');
|
||||
console.error('Error adding keypair:', error);
|
||||
showToast(errorMsg, 'error');
|
||||
} finally {
|
||||
setButtonLoading(elements.addKeypairBtn, false);
|
||||
}
|
||||
}
|
||||
|
||||
async function loadKeypairs() {
|
||||
try {
|
||||
console.log('Loading keypairs...');
|
||||
const response = await sendMessage('listKeypairs');
|
||||
console.log('Keypairs response:', response);
|
||||
|
||||
if (response && response.success) {
|
||||
console.log('Keypairs data:', response.keypairs);
|
||||
console.log('Keypairs data type:', typeof response.keypairs);
|
||||
renderKeypairs(response.keypairs);
|
||||
} else {
|
||||
const errorMsg = getResponseError(response, 'load keypairs');
|
||||
console.error('Failed to load keypairs:', response);
|
||||
const container = elements.keypairsList;
|
||||
container.innerHTML = '<div class="empty-state">Failed to load keypairs. Try refreshing.</div>';
|
||||
showToast(errorMsg, 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
const errorMsg = getErrorMessage(error, 'Failed to load keypairs');
|
||||
console.error('Error loading keypairs:', error);
|
||||
const container = elements.keypairsList;
|
||||
container.innerHTML = '<div class="empty-state">Error loading keypairs. Try refreshing.</div>';
|
||||
showToast(errorMsg, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
function renderKeypairs(keypairs) {
|
||||
console.log('Rendering keypairs:', keypairs);
|
||||
console.log('Keypairs type:', typeof keypairs);
|
||||
console.log('Keypairs is array:', Array.isArray(keypairs));
|
||||
|
||||
const container = elements.keypairsList;
|
||||
|
||||
// Handle different data types that might be returned
|
||||
let keypairArray = [];
|
||||
|
||||
if (Array.isArray(keypairs)) {
|
||||
keypairArray = keypairs;
|
||||
} else if (keypairs && typeof keypairs === 'object') {
|
||||
// If it's an object, try to extract array from common properties
|
||||
if (keypairs.keypairs && Array.isArray(keypairs.keypairs)) {
|
||||
keypairArray = keypairs.keypairs;
|
||||
} else if (keypairs.data && Array.isArray(keypairs.data)) {
|
||||
keypairArray = keypairs.data;
|
||||
} else {
|
||||
console.log('Keypairs object structure:', Object.keys(keypairs));
|
||||
// Try to convert object to array if it has numeric keys
|
||||
const keys = Object.keys(keypairs);
|
||||
if (keys.length > 0 && keys.every(key => !isNaN(key))) {
|
||||
keypairArray = Object.values(keypairs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Final keypair array:', keypairArray);
|
||||
console.log('Array length:', keypairArray.length);
|
||||
|
||||
if (!keypairArray || keypairArray.length === 0) {
|
||||
console.log('No keypairs to render');
|
||||
container.innerHTML = '<div class="empty-state">No keypairs found. Add one above.</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('Rendering', keypairArray.length, 'keypairs');
|
||||
container.innerHTML = keypairArray.map((keypair, index) => {
|
||||
console.log('Processing keypair:', keypair);
|
||||
const metadata = typeof keypair.metadata === 'string'
|
||||
? JSON.parse(keypair.metadata)
|
||||
: keypair.metadata;
|
||||
|
||||
return `
|
||||
<div class="keypair-item" data-id="${keypair.id}">
|
||||
<div class="keypair-info">
|
||||
<div class="keypair-name">${metadata.name || 'Unnamed'}</div>
|
||||
<div class="keypair-type">${keypair.key_type}</div>
|
||||
</div>
|
||||
<button class="btn btn-small select-btn" data-keypair-id="${keypair.id}" data-index="${index}">
|
||||
Select
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
}).join('');
|
||||
|
||||
// Add event listeners to all select buttons
|
||||
const selectButtons = container.querySelectorAll('.select-btn');
|
||||
selectButtons.forEach(button => {
|
||||
button.addEventListener('click', (e) => {
|
||||
e.preventDefault(); // Prevent any default button behavior
|
||||
e.stopPropagation(); // Stop event bubbling
|
||||
|
||||
const keypairId = e.target.getAttribute('data-keypair-id');
|
||||
console.log('Select button clicked for keypair:', keypairId);
|
||||
selectKeypair(keypairId);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function selectKeypair(keyId) {
|
||||
console.log('Selecting keypair:', keyId);
|
||||
|
||||
// Don't show loading overlay for selection - it's too disruptive
|
||||
try {
|
||||
// Update visual state immediately for better UX
|
||||
updateKeypairSelection(keyId);
|
||||
|
||||
await sendMessage('selectKeypair', { keyId });
|
||||
selectedKeypairId = keyId;
|
||||
|
||||
// Get keypair details for internal use (but don't show the card)
|
||||
const metadataResponse = await sendMessage('getCurrentKeypairMetadata');
|
||||
const publicKeyResponse = await sendMessage('getCurrentKeypairPublicKey');
|
||||
|
||||
if (metadataResponse && metadataResponse.success && publicKeyResponse && publicKeyResponse.success) {
|
||||
const metadata = metadataResponse.metadata;
|
||||
|
||||
// Store the details in hidden elements for internal use
|
||||
document.getElementById('selectedName').textContent = metadata.name || 'Unnamed';
|
||||
document.getElementById('selectedType').textContent = metadata.key_type;
|
||||
document.getElementById('selectedPublicKey').textContent = publicKeyResponse.publicKey;
|
||||
|
||||
// Enable sign button if message is entered
|
||||
elements.signBtn.disabled = !elements.messageInput.value.trim();
|
||||
|
||||
// Show a subtle success message without toast
|
||||
console.log(`Keypair "${metadata.name}" selected successfully`);
|
||||
} else {
|
||||
// Handle metadata or public key fetch failure
|
||||
const metadataError = getResponseError(metadataResponse, 'get keypair metadata');
|
||||
const publicKeyError = getResponseError(publicKeyResponse, 'get public key');
|
||||
const errorMsg = metadataResponse && !metadataResponse.success ? metadataError : publicKeyError;
|
||||
|
||||
console.error('Failed to get keypair details:', { metadataResponse, publicKeyResponse });
|
||||
updateKeypairSelection(null);
|
||||
showToast(errorMsg, 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
const errorMsg = getErrorMessage(error, 'Failed to select keypair');
|
||||
console.error('Error selecting keypair:', error);
|
||||
// Revert visual state if there was an error
|
||||
updateKeypairSelection(null);
|
||||
showToast(errorMsg, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
function updateKeypairSelection(selectedId) {
|
||||
// Remove previous selection styling
|
||||
const allKeypairs = document.querySelectorAll('.keypair-item');
|
||||
allKeypairs.forEach(item => {
|
||||
item.classList.remove('selected');
|
||||
const button = item.querySelector('.select-btn');
|
||||
button.textContent = 'Select';
|
||||
button.classList.remove('selected');
|
||||
});
|
||||
|
||||
// Add selection styling to the selected keypair (if any)
|
||||
if (selectedId) {
|
||||
const selectedKeypair = document.querySelector(`[data-id="${selectedId}"]`);
|
||||
if (selectedKeypair) {
|
||||
selectedKeypair.classList.add('selected');
|
||||
const button = selectedKeypair.querySelector('.select-btn');
|
||||
button.textContent = 'Selected';
|
||||
button.classList.add('selected');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function signMessage() {
|
||||
const messageText = elements.messageInput.value.trim();
|
||||
if (!messageText || !selectedKeypairId) {
|
||||
showToast('Please enter a message and select a keypair', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
// Use button loading and show inline loading in signature area
|
||||
setButtonLoading(elements.signBtn, true);
|
||||
|
||||
// Show loading in signature result area
|
||||
elements.signatureResult.classList.remove('hidden');
|
||||
showInlineLoading(elements.signatureResult, 'Signing message...');
|
||||
|
||||
try {
|
||||
const messageBytes = stringToUint8Array(messageText);
|
||||
const response = await sendMessage('sign', { message: messageBytes });
|
||||
|
||||
if (response && response.success) {
|
||||
// Restore signature result structure and show signature
|
||||
elements.signatureResult.innerHTML = `
|
||||
<label>Signature:</label>
|
||||
<div class="signature-container">
|
||||
<code id="signatureValue">${response.signature}</code>
|
||||
<button id="copySignatureBtn" class="btn-copy" title="Copy to clipboard">📋</button>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// Re-attach copy event listener
|
||||
document.getElementById('copySignatureBtn').addEventListener('click', () => {
|
||||
copyToClipboard(response.signature);
|
||||
});
|
||||
|
||||
showToast('Message signed successfully!', 'success');
|
||||
} else {
|
||||
const errorMsg = getResponseError(response, 'sign message');
|
||||
elements.signatureResult.classList.add('hidden');
|
||||
showToast(errorMsg, 'error');
|
||||
}
|
||||
} catch (error) {
|
||||
const errorMsg = getErrorMessage(error, 'Failed to sign message');
|
||||
console.error('Sign message error:', error);
|
||||
elements.signatureResult.classList.add('hidden');
|
||||
showToast(errorMsg, 'error');
|
||||
} finally {
|
||||
setButtonLoading(elements.signBtn, false);
|
||||
}
|
||||
}
|
||||
|
||||
// selectKeypair is now handled via event listeners, no need for global access
|
654
crypto_vault_extension/styles/popup.css
Normal file
654
crypto_vault_extension/styles/popup.css
Normal file
@ -0,0 +1,654 @@
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
body {
|
||||
width: 400px;
|
||||
min-height: 600px;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
background-attachment: fixed;
|
||||
color: #333;
|
||||
line-height: 1.6;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.container {
|
||||
position: relative;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* Header */
|
||||
.header {
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
backdrop-filter: blur(20px);
|
||||
padding: 20px;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
|
||||
.logo {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.logo-icon {
|
||||
font-size: 24px;
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
.logo h1 {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
color: #2d3748;
|
||||
}
|
||||
|
||||
.status-indicator {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.status-dot {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
background-color: #fbbf24;
|
||||
margin-right: 8px;
|
||||
animation: pulse 2s infinite;
|
||||
}
|
||||
|
||||
.status-indicator.connected .status-dot {
|
||||
background-color: #10b981;
|
||||
animation: none;
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0%, 100% { opacity: 1; }
|
||||
50% { opacity: 0.5; }
|
||||
}
|
||||
|
||||
/* Sections */
|
||||
.section {
|
||||
padding: 20px;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.section:last-child {
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
.section.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.completely-hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Cards */
|
||||
.card {
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
backdrop-filter: blur(20px);
|
||||
border-radius: 16px;
|
||||
padding: 20px;
|
||||
margin-bottom: 16px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.3);
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.card h2, .card h3 {
|
||||
margin-bottom: 16px;
|
||||
color: #2d3748;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.card h2 {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.card h3 {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
/* Forms */
|
||||
.form-group {
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.form-row {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
align-items: end;
|
||||
}
|
||||
|
||||
label {
|
||||
display: block;
|
||||
margin-bottom: 6px;
|
||||
font-weight: 500;
|
||||
color: #4a5568;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
input, select, textarea {
|
||||
width: 100%;
|
||||
padding: 12px 16px;
|
||||
border: 2px solid rgba(255, 255, 255, 0.3);
|
||||
border-radius: 12px;
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
font-size: 14px;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
input:focus, select:focus, textarea:focus {
|
||||
outline: none;
|
||||
border-color: #667eea;
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
|
||||
}
|
||||
|
||||
.select {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
/* Buttons */
|
||||
.btn {
|
||||
padding: 12px 24px;
|
||||
border: none;
|
||||
border-radius: 12px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
text-decoration: none;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 8px 25px rgba(102, 126, 234, 0.3);
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
color: #4a5568;
|
||||
border: 2px solid rgba(102, 126, 234, 0.2);
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
border-color: rgba(102, 126, 234, 0.4);
|
||||
}
|
||||
|
||||
.btn-ghost {
|
||||
background: transparent;
|
||||
color: #667eea;
|
||||
border: 1px solid rgba(102, 126, 234, 0.3);
|
||||
}
|
||||
|
||||
.btn-ghost:hover {
|
||||
background: rgba(102, 126, 234, 0.1);
|
||||
}
|
||||
|
||||
.btn-small {
|
||||
padding: 8px 16px;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.btn:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
transform: none !important;
|
||||
}
|
||||
|
||||
.btn.loading {
|
||||
position: relative;
|
||||
color: transparent !important;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.btn.loading::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin: -8px 0 0 -8px;
|
||||
border: 2px solid transparent;
|
||||
border-top: 2px solid currentColor;
|
||||
border-radius: 50%;
|
||||
animation: btn-spin 0.8s linear infinite;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-secondary.loading::after {
|
||||
color: #4a5568;
|
||||
}
|
||||
|
||||
@keyframes btn-spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
/* Inline Loading Components */
|
||||
.inline-loading {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
padding: 8px;
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.inline-spinner {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border: 2px solid rgba(102, 126, 234, 0.2);
|
||||
border-top: 2px solid #667eea;
|
||||
border-radius: 50%;
|
||||
animation: btn-spin 0.8s linear infinite;
|
||||
}
|
||||
|
||||
.button-group {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.btn-copy {
|
||||
background: transparent;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
padding: 4px;
|
||||
border-radius: 6px;
|
||||
transition: background 0.2s ease;
|
||||
}
|
||||
|
||||
.btn-copy:hover {
|
||||
background: rgba(102, 126, 234, 0.1);
|
||||
}
|
||||
|
||||
/* Vault Header */
|
||||
.vault-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.vault-header h2 {
|
||||
color: white;
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* Add Keypair Toggle */
|
||||
.add-keypair-toggle {
|
||||
margin-bottom: 16px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.btn-icon {
|
||||
margin-right: 8px;
|
||||
font-weight: bold;
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
|
||||
.add-keypair-form {
|
||||
transform: translateY(-10px);
|
||||
opacity: 0;
|
||||
transition: all 0.3s ease;
|
||||
max-height: 0;
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.add-keypair-form:not(.hidden) {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
max-height: 300px;
|
||||
padding: 20px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.form-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 16px;
|
||||
padding-bottom: 12px;
|
||||
border-bottom: 1px solid rgba(102, 126, 234, 0.1);
|
||||
}
|
||||
|
||||
.form-header h3 {
|
||||
margin: 0;
|
||||
color: #2d3748;
|
||||
}
|
||||
|
||||
.btn-close {
|
||||
background: none;
|
||||
border: none;
|
||||
font-size: 20px;
|
||||
color: #666;
|
||||
cursor: pointer;
|
||||
padding: 4px 8px;
|
||||
border-radius: 6px;
|
||||
transition: all 0.2s ease;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.btn-close:hover {
|
||||
background: rgba(239, 68, 68, 0.1);
|
||||
color: #ef4444;
|
||||
}
|
||||
|
||||
.form-content {
|
||||
animation: slideInUp 0.3s ease-out;
|
||||
}
|
||||
|
||||
.form-actions {
|
||||
margin-top: 16px;
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
/* Keypairs List */
|
||||
.keypairs-list {
|
||||
max-height: 200px;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.keypair-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 12px;
|
||||
border-radius: 8px;
|
||||
margin-bottom: 8px;
|
||||
background: rgba(102, 126, 234, 0.05);
|
||||
border: 1px solid rgba(102, 126, 234, 0.1);
|
||||
transition: all 0.2s ease;
|
||||
min-width: 0; /* Allow flex items to shrink */
|
||||
}
|
||||
|
||||
.keypair-item:hover {
|
||||
background: rgba(102, 126, 234, 0.1);
|
||||
transform: translateX(4px);
|
||||
}
|
||||
|
||||
.keypair-item.selected {
|
||||
background: rgba(16, 185, 129, 0.1);
|
||||
border-color: rgba(16, 185, 129, 0.3);
|
||||
transform: translateX(4px);
|
||||
}
|
||||
|
||||
.keypair-item.selected .keypair-name {
|
||||
color: #065f46;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.keypair-item.selected .select-btn {
|
||||
background: rgba(16, 185, 129, 0.2);
|
||||
color: #065f46;
|
||||
border-color: rgba(16, 185, 129, 0.3);
|
||||
}
|
||||
|
||||
.keypair-item.selected .select-btn:hover {
|
||||
background: rgba(16, 185, 129, 0.3);
|
||||
}
|
||||
|
||||
.keypair-info {
|
||||
flex: 1;
|
||||
min-width: 0; /* Allow shrinking */
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
.keypair-name {
|
||||
font-weight: 500;
|
||||
color: #2d3748;
|
||||
word-break: break-word; /* Break long names */
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.keypair-type {
|
||||
font-size: 12px;
|
||||
color: #666;
|
||||
background: rgba(102, 126, 234, 0.1);
|
||||
padding: 2px 8px;
|
||||
border-radius: 12px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.empty-state, .loading {
|
||||
text-align: center;
|
||||
color: #666;
|
||||
font-style: italic;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
/* Selected Keypair Info */
|
||||
.keypair-info .info-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 8px;
|
||||
padding: 8px 0;
|
||||
border-bottom: 1px solid rgba(102, 126, 234, 0.1);
|
||||
}
|
||||
|
||||
.keypair-info .info-row:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.keypair-info label {
|
||||
font-weight: 500;
|
||||
color: #4a5568;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.public-key-container, .signature-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
flex: 1;
|
||||
margin-left: 12px;
|
||||
}
|
||||
|
||||
.keypair-info code, .signature-result code {
|
||||
background: rgba(102, 126, 234, 0.1);
|
||||
padding: 6px 10px;
|
||||
border-radius: 6px;
|
||||
font-size: 11px;
|
||||
word-break: break-all;
|
||||
flex: 1;
|
||||
color: #2d3748;
|
||||
}
|
||||
|
||||
/* Signature Result */
|
||||
.signature-result {
|
||||
margin-top: 16px;
|
||||
padding: 16px;
|
||||
background: rgba(16, 185, 129, 0.1);
|
||||
border-radius: 12px;
|
||||
border: 1px solid rgba(16, 185, 129, 0.2);
|
||||
}
|
||||
|
||||
.signature-result.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.signature-result label {
|
||||
color: #065f46;
|
||||
font-weight: 500;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
/* Loading Overlay */
|
||||
.loading-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
backdrop-filter: blur(8px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.loading-overlay.hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border: 3px solid rgba(102, 126, 234, 0.3);
|
||||
border-top: 3px solid #667eea;
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
0% { transform: rotate(0deg); }
|
||||
100% { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
/* Toast Notifications */
|
||||
.toast {
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
left: 20px;
|
||||
right: 20px;
|
||||
max-width: 360px;
|
||||
margin: 0 auto;
|
||||
padding: 12px 16px;
|
||||
border-radius: 12px;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
z-index: 1001;
|
||||
transform: translateY(-100px);
|
||||
opacity: 0;
|
||||
transition: all 0.3s ease;
|
||||
backdrop-filter: blur(20px);
|
||||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.toast:not(.hidden) {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.toast.success {
|
||||
background: rgba(16, 185, 129, 0.9);
|
||||
color: white;
|
||||
border: 1px solid rgba(16, 185, 129, 1);
|
||||
}
|
||||
|
||||
.toast.error {
|
||||
background: rgba(239, 68, 68, 0.9);
|
||||
color: white;
|
||||
border: 1px solid rgba(239, 68, 68, 1);
|
||||
}
|
||||
|
||||
.toast.info {
|
||||
background: rgba(59, 130, 246, 0.9);
|
||||
color: white;
|
||||
border: 1px solid rgba(59, 130, 246, 1);
|
||||
}
|
||||
|
||||
/* Scrollbar Styles */
|
||||
.keypairs-list::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
.keypairs-list::-webkit-scrollbar-track {
|
||||
background: rgba(102, 126, 234, 0.1);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.keypairs-list::-webkit-scrollbar-thumb {
|
||||
background: rgba(102, 126, 234, 0.3);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.keypairs-list::-webkit-scrollbar-thumb:hover {
|
||||
background: rgba(102, 126, 234, 0.5);
|
||||
}
|
||||
|
||||
/* Responsive adjustments */
|
||||
@media (max-width: 400px) {
|
||||
body {
|
||||
width: 350px;
|
||||
}
|
||||
|
||||
.form-row {
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.button-group {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
/* Animation for card entrance */
|
||||
.card {
|
||||
animation: slideInUp 0.3s ease-out;
|
||||
}
|
||||
|
||||
@keyframes slideInUp {
|
||||
from {
|
||||
transform: translateY(20px);
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
transform: translateY(0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Hover effects for better UX */
|
||||
.keypair-item {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.keypair-item::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
|
||||
transition: left 0.5s;
|
||||
}
|
||||
|
||||
.keypair-item:hover::before {
|
||||
left: 100%;
|
||||
}
|
822
crypto_vault_extension/wasm/wasm_app.js
Normal file
822
crypto_vault_extension/wasm/wasm_app.js
Normal file
@ -0,0 +1,822 @@
|
||||
let wasm;
|
||||
|
||||
function addToExternrefTable0(obj) {
|
||||
const idx = wasm.__externref_table_alloc();
|
||||
wasm.__wbindgen_export_2.set(idx, obj);
|
||||
return idx;
|
||||
}
|
||||
|
||||
function handleError(f, args) {
|
||||
try {
|
||||
return f.apply(this, args);
|
||||
} catch (e) {
|
||||
const idx = addToExternrefTable0(e);
|
||||
wasm.__wbindgen_exn_store(idx);
|
||||
}
|
||||
}
|
||||
|
||||
const cachedTextDecoder = (typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-8', { ignoreBOM: true, fatal: true }) : { decode: () => { throw Error('TextDecoder not available') } } );
|
||||
|
||||
if (typeof TextDecoder !== 'undefined') { cachedTextDecoder.decode(); };
|
||||
|
||||
let cachedUint8ArrayMemory0 = null;
|
||||
|
||||
function getUint8ArrayMemory0() {
|
||||
if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
|
||||
cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
|
||||
}
|
||||
return cachedUint8ArrayMemory0;
|
||||
}
|
||||
|
||||
function getStringFromWasm0(ptr, len) {
|
||||
ptr = ptr >>> 0;
|
||||
return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
|
||||
}
|
||||
|
||||
function isLikeNone(x) {
|
||||
return x === undefined || x === null;
|
||||
}
|
||||
|
||||
function getArrayU8FromWasm0(ptr, len) {
|
||||
ptr = ptr >>> 0;
|
||||
return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len);
|
||||
}
|
||||
|
||||
let WASM_VECTOR_LEN = 0;
|
||||
|
||||
const cachedTextEncoder = (typeof TextEncoder !== 'undefined' ? new TextEncoder('utf-8') : { encode: () => { throw Error('TextEncoder not available') } } );
|
||||
|
||||
const encodeString = (typeof cachedTextEncoder.encodeInto === 'function'
|
||||
? function (arg, view) {
|
||||
return cachedTextEncoder.encodeInto(arg, view);
|
||||
}
|
||||
: function (arg, view) {
|
||||
const buf = cachedTextEncoder.encode(arg);
|
||||
view.set(buf);
|
||||
return {
|
||||
read: arg.length,
|
||||
written: buf.length
|
||||
};
|
||||
});
|
||||
|
||||
function passStringToWasm0(arg, malloc, realloc) {
|
||||
|
||||
if (realloc === undefined) {
|
||||
const buf = cachedTextEncoder.encode(arg);
|
||||
const ptr = malloc(buf.length, 1) >>> 0;
|
||||
getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf);
|
||||
WASM_VECTOR_LEN = buf.length;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
let len = arg.length;
|
||||
let ptr = malloc(len, 1) >>> 0;
|
||||
|
||||
const mem = getUint8ArrayMemory0();
|
||||
|
||||
let offset = 0;
|
||||
|
||||
for (; offset < len; offset++) {
|
||||
const code = arg.charCodeAt(offset);
|
||||
if (code > 0x7F) break;
|
||||
mem[ptr + offset] = code;
|
||||
}
|
||||
|
||||
if (offset !== len) {
|
||||
if (offset !== 0) {
|
||||
arg = arg.slice(offset);
|
||||
}
|
||||
ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
|
||||
const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);
|
||||
const ret = encodeString(arg, view);
|
||||
|
||||
offset += ret.written;
|
||||
ptr = realloc(ptr, len, offset, 1) >>> 0;
|
||||
}
|
||||
|
||||
WASM_VECTOR_LEN = offset;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
let cachedDataViewMemory0 = null;
|
||||
|
||||
function getDataViewMemory0() {
|
||||
if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) {
|
||||
cachedDataViewMemory0 = new DataView(wasm.memory.buffer);
|
||||
}
|
||||
return cachedDataViewMemory0;
|
||||
}
|
||||
|
||||
const CLOSURE_DTORS = (typeof FinalizationRegistry === 'undefined')
|
||||
? { register: () => {}, unregister: () => {} }
|
||||
: new FinalizationRegistry(state => {
|
||||
wasm.__wbindgen_export_5.get(state.dtor)(state.a, state.b)
|
||||
});
|
||||
|
||||
function makeMutClosure(arg0, arg1, dtor, f) {
|
||||
const state = { a: arg0, b: arg1, cnt: 1, dtor };
|
||||
const real = (...args) => {
|
||||
// First up with a closure we increment the internal reference
|
||||
// count. This ensures that the Rust closure environment won't
|
||||
// be deallocated while we're invoking it.
|
||||
state.cnt++;
|
||||
const a = state.a;
|
||||
state.a = 0;
|
||||
try {
|
||||
return f(a, state.b, ...args);
|
||||
} finally {
|
||||
if (--state.cnt === 0) {
|
||||
wasm.__wbindgen_export_5.get(state.dtor)(a, state.b);
|
||||
CLOSURE_DTORS.unregister(state);
|
||||
} else {
|
||||
state.a = a;
|
||||
}
|
||||
}
|
||||
};
|
||||
real.original = state;
|
||||
CLOSURE_DTORS.register(real, state, state);
|
||||
return real;
|
||||
}
|
||||
|
||||
function debugString(val) {
|
||||
// primitive types
|
||||
const type = typeof val;
|
||||
if (type == 'number' || type == 'boolean' || val == null) {
|
||||
return `${val}`;
|
||||
}
|
||||
if (type == 'string') {
|
||||
return `"${val}"`;
|
||||
}
|
||||
if (type == 'symbol') {
|
||||
const description = val.description;
|
||||
if (description == null) {
|
||||
return 'Symbol';
|
||||
} else {
|
||||
return `Symbol(${description})`;
|
||||
}
|
||||
}
|
||||
if (type == 'function') {
|
||||
const name = val.name;
|
||||
if (typeof name == 'string' && name.length > 0) {
|
||||
return `Function(${name})`;
|
||||
} else {
|
||||
return 'Function';
|
||||
}
|
||||
}
|
||||
// objects
|
||||
if (Array.isArray(val)) {
|
||||
const length = val.length;
|
||||
let debug = '[';
|
||||
if (length > 0) {
|
||||
debug += debugString(val[0]);
|
||||
}
|
||||
for(let i = 1; i < length; i++) {
|
||||
debug += ', ' + debugString(val[i]);
|
||||
}
|
||||
debug += ']';
|
||||
return debug;
|
||||
}
|
||||
// Test for built-in
|
||||
const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val));
|
||||
let className;
|
||||
if (builtInMatches && builtInMatches.length > 1) {
|
||||
className = builtInMatches[1];
|
||||
} else {
|
||||
// Failed to match the standard '[object ClassName]'
|
||||
return toString.call(val);
|
||||
}
|
||||
if (className == 'Object') {
|
||||
// we're a user defined class or Object
|
||||
// JSON.stringify avoids problems with cycles, and is generally much
|
||||
// easier than looping through ownProperties of `val`.
|
||||
try {
|
||||
return 'Object(' + JSON.stringify(val) + ')';
|
||||
} catch (_) {
|
||||
return 'Object';
|
||||
}
|
||||
}
|
||||
// errors
|
||||
if (val instanceof Error) {
|
||||
return `${val.name}: ${val.message}\n${val.stack}`;
|
||||
}
|
||||
// TODO we could test for more things here, like `Set`s and `Map`s.
|
||||
return className;
|
||||
}
|
||||
/**
|
||||
* Initialize the scripting environment (must be called before run_rhai)
|
||||
*/
|
||||
export function init_rhai_env() {
|
||||
wasm.init_rhai_env();
|
||||
}
|
||||
|
||||
function takeFromExternrefTable0(idx) {
|
||||
const value = wasm.__wbindgen_export_2.get(idx);
|
||||
wasm.__externref_table_dealloc(idx);
|
||||
return value;
|
||||
}
|
||||
/**
|
||||
* Securely run a Rhai script in the extension context (must be called only after user approval)
|
||||
* @param {string} script
|
||||
* @returns {any}
|
||||
*/
|
||||
export function run_rhai(script) {
|
||||
const ptr0 = passStringToWasm0(script, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
const ret = wasm.run_rhai(ptr0, len0);
|
||||
if (ret[2]) {
|
||||
throw takeFromExternrefTable0(ret[1]);
|
||||
}
|
||||
return takeFromExternrefTable0(ret[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and unlock a new keyspace with the given name and password
|
||||
* @param {string} keyspace
|
||||
* @param {string} password
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
export function create_keyspace(keyspace, password) {
|
||||
const ptr0 = passStringToWasm0(keyspace, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
const ptr1 = passStringToWasm0(password, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len1 = WASM_VECTOR_LEN;
|
||||
const ret = wasm.create_keyspace(ptr0, len0, ptr1, len1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize session with keyspace and password
|
||||
* @param {string} keyspace
|
||||
* @param {string} password
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
export function init_session(keyspace, password) {
|
||||
const ptr0 = passStringToWasm0(keyspace, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
const ptr1 = passStringToWasm0(password, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len1 = WASM_VECTOR_LEN;
|
||||
const ret = wasm.init_session(ptr0, len0, ptr1, len1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lock the session (zeroize password and session)
|
||||
*/
|
||||
export function lock_session() {
|
||||
wasm.lock_session();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get metadata of the currently selected keypair
|
||||
* @returns {any}
|
||||
*/
|
||||
export function current_keypair_metadata() {
|
||||
const ret = wasm.current_keypair_metadata();
|
||||
if (ret[2]) {
|
||||
throw takeFromExternrefTable0(ret[1]);
|
||||
}
|
||||
return takeFromExternrefTable0(ret[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get public key of the currently selected keypair as Uint8Array
|
||||
* @returns {any}
|
||||
*/
|
||||
export function current_keypair_public_key() {
|
||||
const ret = wasm.current_keypair_public_key();
|
||||
if (ret[2]) {
|
||||
throw takeFromExternrefTable0(ret[1]);
|
||||
}
|
||||
return takeFromExternrefTable0(ret[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if a keyspace is currently unlocked
|
||||
* @returns {boolean}
|
||||
*/
|
||||
export function is_unlocked() {
|
||||
const ret = wasm.is_unlocked();
|
||||
return ret !== 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all keypairs from the current session
|
||||
* Returns an array of keypair objects with id, type, and metadata
|
||||
* Select keypair for the session
|
||||
* @param {string} key_id
|
||||
*/
|
||||
export function select_keypair(key_id) {
|
||||
const ptr0 = passStringToWasm0(key_id, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
const ret = wasm.select_keypair(ptr0, len0);
|
||||
if (ret[1]) {
|
||||
throw takeFromExternrefTable0(ret[0]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* List keypairs in the current session's keyspace
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
export function list_keypairs() {
|
||||
const ret = wasm.list_keypairs();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a keypair to the current keyspace
|
||||
* @param {string | null} [key_type]
|
||||
* @param {string | null} [metadata]
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
export function add_keypair(key_type, metadata) {
|
||||
var ptr0 = isLikeNone(key_type) ? 0 : passStringToWasm0(key_type, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
var len0 = WASM_VECTOR_LEN;
|
||||
var ptr1 = isLikeNone(metadata) ? 0 : passStringToWasm0(metadata, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
var len1 = WASM_VECTOR_LEN;
|
||||
const ret = wasm.add_keypair(ptr0, len0, ptr1, len1);
|
||||
return ret;
|
||||
}
|
||||
|
||||
function passArray8ToWasm0(arg, malloc) {
|
||||
const ptr = malloc(arg.length * 1, 1) >>> 0;
|
||||
getUint8ArrayMemory0().set(arg, ptr / 1);
|
||||
WASM_VECTOR_LEN = arg.length;
|
||||
return ptr;
|
||||
}
|
||||
/**
|
||||
* Sign message with current session
|
||||
* @param {Uint8Array} message
|
||||
* @returns {Promise<any>}
|
||||
*/
|
||||
export function sign(message) {
|
||||
const ptr0 = passArray8ToWasm0(message, wasm.__wbindgen_malloc);
|
||||
const len0 = WASM_VECTOR_LEN;
|
||||
const ret = wasm.sign(ptr0, len0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
function __wbg_adapter_32(arg0, arg1, arg2) {
|
||||
wasm.closure89_externref_shim(arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
function __wbg_adapter_35(arg0, arg1, arg2) {
|
||||
wasm.closure133_externref_shim(arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
function __wbg_adapter_38(arg0, arg1, arg2) {
|
||||
wasm.closure188_externref_shim(arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
function __wbg_adapter_135(arg0, arg1, arg2, arg3) {
|
||||
wasm.closure1847_externref_shim(arg0, arg1, arg2, arg3);
|
||||
}
|
||||
|
||||
const __wbindgen_enum_IdbTransactionMode = ["readonly", "readwrite", "versionchange", "readwriteflush", "cleanup"];
|
||||
|
||||
async function __wbg_load(module, imports) {
|
||||
if (typeof Response === 'function' && module instanceof Response) {
|
||||
if (typeof WebAssembly.instantiateStreaming === 'function') {
|
||||
try {
|
||||
return await WebAssembly.instantiateStreaming(module, imports);
|
||||
|
||||
} catch (e) {
|
||||
if (module.headers.get('Content-Type') != 'application/wasm') {
|
||||
console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve Wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
|
||||
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const bytes = await module.arrayBuffer();
|
||||
return await WebAssembly.instantiate(bytes, imports);
|
||||
|
||||
} else {
|
||||
const instance = await WebAssembly.instantiate(module, imports);
|
||||
|
||||
if (instance instanceof WebAssembly.Instance) {
|
||||
return { instance, module };
|
||||
|
||||
} else {
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function __wbg_get_imports() {
|
||||
const imports = {};
|
||||
imports.wbg = {};
|
||||
imports.wbg.__wbg_buffer_609cc3eee51ed158 = function(arg0) {
|
||||
const ret = arg0.buffer;
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbg_call_672a4d21634d4a24 = function() { return handleError(function (arg0, arg1) {
|
||||
const ret = arg0.call(arg1);
|
||||
return ret;
|
||||
}, arguments) };
|
||||
imports.wbg.__wbg_call_7cccdd69e0791ae2 = function() { return handleError(function (arg0, arg1, arg2) {
|
||||
const ret = arg0.call(arg1, arg2);
|
||||
return ret;
|
||||
}, arguments) };
|
||||
imports.wbg.__wbg_createObjectStore_d2f9e1016f4d81b9 = function() { return handleError(function (arg0, arg1, arg2, arg3) {
|
||||
const ret = arg0.createObjectStore(getStringFromWasm0(arg1, arg2), arg3);
|
||||
return ret;
|
||||
}, arguments) };
|
||||
imports.wbg.__wbg_crypto_574e78ad8b13b65f = function(arg0) {
|
||||
const ret = arg0.crypto;
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbg_error_524f506f44df1645 = function(arg0) {
|
||||
console.error(arg0);
|
||||
};
|
||||
imports.wbg.__wbg_error_ff4ddaabdfc5dbb3 = function() { return handleError(function (arg0) {
|
||||
const ret = arg0.error;
|
||||
return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);
|
||||
}, arguments) };
|
||||
imports.wbg.__wbg_getRandomValues_3c9c0d586e575a16 = function() { return handleError(function (arg0, arg1) {
|
||||
globalThis.crypto.getRandomValues(getArrayU8FromWasm0(arg0, arg1));
|
||||
}, arguments) };
|
||||
imports.wbg.__wbg_getRandomValues_b8f5dbd5f3995a9e = function() { return handleError(function (arg0, arg1) {
|
||||
arg0.getRandomValues(arg1);
|
||||
}, arguments) };
|
||||
imports.wbg.__wbg_getTime_46267b1c24877e30 = function(arg0) {
|
||||
const ret = arg0.getTime();
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbg_get_4f73335ab78445db = function(arg0, arg1, arg2) {
|
||||
const ret = arg1[arg2 >>> 0];
|
||||
var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
var len1 = WASM_VECTOR_LEN;
|
||||
getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
|
||||
getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
|
||||
};
|
||||
imports.wbg.__wbg_get_67b2ba62fc30de12 = function() { return handleError(function (arg0, arg1) {
|
||||
const ret = Reflect.get(arg0, arg1);
|
||||
return ret;
|
||||
}, arguments) };
|
||||
imports.wbg.__wbg_get_8da03f81f6a1111e = function() { return handleError(function (arg0, arg1) {
|
||||
const ret = arg0.get(arg1);
|
||||
return ret;
|
||||
}, arguments) };
|
||||
imports.wbg.__wbg_instanceof_IdbDatabase_a3ef009ca00059f9 = function(arg0) {
|
||||
let result;
|
||||
try {
|
||||
result = arg0 instanceof IDBDatabase;
|
||||
} catch (_) {
|
||||
result = false;
|
||||
}
|
||||
const ret = result;
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbg_instanceof_IdbFactory_12eaba3366f4302f = function(arg0) {
|
||||
let result;
|
||||
try {
|
||||
result = arg0 instanceof IDBFactory;
|
||||
} catch (_) {
|
||||
result = false;
|
||||
}
|
||||
const ret = result;
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbg_instanceof_IdbOpenDbRequest_a3416e156c9db893 = function(arg0) {
|
||||
let result;
|
||||
try {
|
||||
result = arg0 instanceof IDBOpenDBRequest;
|
||||
} catch (_) {
|
||||
result = false;
|
||||
}
|
||||
const ret = result;
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbg_instanceof_IdbRequest_4813c3f207666aa4 = function(arg0) {
|
||||
let result;
|
||||
try {
|
||||
result = arg0 instanceof IDBRequest;
|
||||
} catch (_) {
|
||||
result = false;
|
||||
}
|
||||
const ret = result;
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbg_length_52b6c4580c5ec934 = function(arg0) {
|
||||
const ret = arg0.length;
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbg_msCrypto_a61aeb35a24c1329 = function(arg0) {
|
||||
const ret = arg0.msCrypto;
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbg_new0_f788a2397c7ca929 = function() {
|
||||
const ret = new Date();
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbg_new_23a2665fac83c611 = function(arg0, arg1) {
|
||||
try {
|
||||
var state0 = {a: arg0, b: arg1};
|
||||
var cb0 = (arg0, arg1) => {
|
||||
const a = state0.a;
|
||||
state0.a = 0;
|
||||
try {
|
||||
return __wbg_adapter_135(a, state0.b, arg0, arg1);
|
||||
} finally {
|
||||
state0.a = a;
|
||||
}
|
||||
};
|
||||
const ret = new Promise(cb0);
|
||||
return ret;
|
||||
} finally {
|
||||
state0.a = state0.b = 0;
|
||||
}
|
||||
};
|
||||
imports.wbg.__wbg_new_405e22f390576ce2 = function() {
|
||||
const ret = new Object();
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbg_new_78feb108b6472713 = function() {
|
||||
const ret = new Array();
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbg_new_a12002a7f91c75be = function(arg0) {
|
||||
const ret = new Uint8Array(arg0);
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbg_newnoargs_105ed471475aaf50 = function(arg0, arg1) {
|
||||
const ret = new Function(getStringFromWasm0(arg0, arg1));
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbg_newwithbyteoffsetandlength_d97e637ebe145a9a = function(arg0, arg1, arg2) {
|
||||
const ret = new Uint8Array(arg0, arg1 >>> 0, arg2 >>> 0);
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbg_newwithlength_a381634e90c276d4 = function(arg0) {
|
||||
const ret = new Uint8Array(arg0 >>> 0);
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbg_node_905d3e251edff8a2 = function(arg0) {
|
||||
const ret = arg0.node;
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbg_now_d18023d54d4e5500 = function(arg0) {
|
||||
const ret = arg0.now();
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbg_objectStoreNames_9bb1ab04a7012aaf = function(arg0) {
|
||||
const ret = arg0.objectStoreNames;
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbg_objectStore_21878d46d25b64b6 = function() { return handleError(function (arg0, arg1, arg2) {
|
||||
const ret = arg0.objectStore(getStringFromWasm0(arg1, arg2));
|
||||
return ret;
|
||||
}, arguments) };
|
||||
imports.wbg.__wbg_open_88b1390d99a7c691 = function() { return handleError(function (arg0, arg1, arg2) {
|
||||
const ret = arg0.open(getStringFromWasm0(arg1, arg2));
|
||||
return ret;
|
||||
}, arguments) };
|
||||
imports.wbg.__wbg_open_e0c0b2993eb596e1 = function() { return handleError(function (arg0, arg1, arg2, arg3) {
|
||||
const ret = arg0.open(getStringFromWasm0(arg1, arg2), arg3 >>> 0);
|
||||
return ret;
|
||||
}, arguments) };
|
||||
imports.wbg.__wbg_process_dc0fbacc7c1c06f7 = function(arg0) {
|
||||
const ret = arg0.process;
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbg_push_737cfc8c1432c2c6 = function(arg0, arg1) {
|
||||
const ret = arg0.push(arg1);
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbg_put_066faa31a6a88f5b = function() { return handleError(function (arg0, arg1, arg2) {
|
||||
const ret = arg0.put(arg1, arg2);
|
||||
return ret;
|
||||
}, arguments) };
|
||||
imports.wbg.__wbg_put_9ef5363941008835 = function() { return handleError(function (arg0, arg1) {
|
||||
const ret = arg0.put(arg1);
|
||||
return ret;
|
||||
}, arguments) };
|
||||
imports.wbg.__wbg_queueMicrotask_97d92b4fcc8a61c5 = function(arg0) {
|
||||
queueMicrotask(arg0);
|
||||
};
|
||||
imports.wbg.__wbg_queueMicrotask_d3219def82552485 = function(arg0) {
|
||||
const ret = arg0.queueMicrotask;
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbg_randomFillSync_ac0988aba3254290 = function() { return handleError(function (arg0, arg1) {
|
||||
arg0.randomFillSync(arg1);
|
||||
}, arguments) };
|
||||
imports.wbg.__wbg_require_60cc747a6bc5215a = function() { return handleError(function () {
|
||||
const ret = module.require;
|
||||
return ret;
|
||||
}, arguments) };
|
||||
imports.wbg.__wbg_resolve_4851785c9c5f573d = function(arg0) {
|
||||
const ret = Promise.resolve(arg0);
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbg_result_f29afabdf2c05826 = function() { return handleError(function (arg0) {
|
||||
const ret = arg0.result;
|
||||
return ret;
|
||||
}, arguments) };
|
||||
imports.wbg.__wbg_set_65595bdd868b3009 = function(arg0, arg1, arg2) {
|
||||
arg0.set(arg1, arg2 >>> 0);
|
||||
};
|
||||
imports.wbg.__wbg_setonerror_d7e3056cc6e56085 = function(arg0, arg1) {
|
||||
arg0.onerror = arg1;
|
||||
};
|
||||
imports.wbg.__wbg_setonsuccess_afa464ee777a396d = function(arg0, arg1) {
|
||||
arg0.onsuccess = arg1;
|
||||
};
|
||||
imports.wbg.__wbg_setonupgradeneeded_fcf7ce4f2eb0cb5f = function(arg0, arg1) {
|
||||
arg0.onupgradeneeded = arg1;
|
||||
};
|
||||
imports.wbg.__wbg_static_accessor_GLOBAL_88a902d13a557d07 = function() {
|
||||
const ret = typeof global === 'undefined' ? null : global;
|
||||
return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);
|
||||
};
|
||||
imports.wbg.__wbg_static_accessor_GLOBAL_THIS_56578be7e9f832b0 = function() {
|
||||
const ret = typeof globalThis === 'undefined' ? null : globalThis;
|
||||
return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);
|
||||
};
|
||||
imports.wbg.__wbg_static_accessor_SELF_37c5d418e4bf5819 = function() {
|
||||
const ret = typeof self === 'undefined' ? null : self;
|
||||
return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);
|
||||
};
|
||||
imports.wbg.__wbg_static_accessor_WINDOW_5de37043a91a9c40 = function() {
|
||||
const ret = typeof window === 'undefined' ? null : window;
|
||||
return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);
|
||||
};
|
||||
imports.wbg.__wbg_subarray_aa9065fa9dc5df96 = function(arg0, arg1, arg2) {
|
||||
const ret = arg0.subarray(arg1 >>> 0, arg2 >>> 0);
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbg_target_0a62d9d79a2a1ede = function(arg0) {
|
||||
const ret = arg0.target;
|
||||
return isLikeNone(ret) ? 0 : addToExternrefTable0(ret);
|
||||
};
|
||||
imports.wbg.__wbg_then_44b73946d2fb3e7d = function(arg0, arg1) {
|
||||
const ret = arg0.then(arg1);
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbg_transaction_d6d07c3c9963c49e = function() { return handleError(function (arg0, arg1, arg2) {
|
||||
const ret = arg0.transaction(arg1, __wbindgen_enum_IdbTransactionMode[arg2]);
|
||||
return ret;
|
||||
}, arguments) };
|
||||
imports.wbg.__wbg_versions_c01dfd4722a88165 = function(arg0) {
|
||||
const ret = arg0.versions;
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbindgen_cb_drop = function(arg0) {
|
||||
const obj = arg0.original;
|
||||
if (obj.cnt-- == 1) {
|
||||
obj.a = 0;
|
||||
return true;
|
||||
}
|
||||
const ret = false;
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbindgen_closure_wrapper288 = function(arg0, arg1, arg2) {
|
||||
const ret = makeMutClosure(arg0, arg1, 90, __wbg_adapter_32);
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbindgen_closure_wrapper518 = function(arg0, arg1, arg2) {
|
||||
const ret = makeMutClosure(arg0, arg1, 134, __wbg_adapter_35);
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbindgen_closure_wrapper776 = function(arg0, arg1, arg2) {
|
||||
const ret = makeMutClosure(arg0, arg1, 189, __wbg_adapter_38);
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbindgen_debug_string = function(arg0, arg1) {
|
||||
const ret = debugString(arg1);
|
||||
const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len1 = WASM_VECTOR_LEN;
|
||||
getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
|
||||
getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
|
||||
};
|
||||
imports.wbg.__wbindgen_init_externref_table = function() {
|
||||
const table = wasm.__wbindgen_export_2;
|
||||
const offset = table.grow(4);
|
||||
table.set(0, undefined);
|
||||
table.set(offset + 0, undefined);
|
||||
table.set(offset + 1, null);
|
||||
table.set(offset + 2, true);
|
||||
table.set(offset + 3, false);
|
||||
;
|
||||
};
|
||||
imports.wbg.__wbindgen_is_function = function(arg0) {
|
||||
const ret = typeof(arg0) === 'function';
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbindgen_is_null = function(arg0) {
|
||||
const ret = arg0 === null;
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbindgen_is_object = function(arg0) {
|
||||
const val = arg0;
|
||||
const ret = typeof(val) === 'object' && val !== null;
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbindgen_is_string = function(arg0) {
|
||||
const ret = typeof(arg0) === 'string';
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbindgen_is_undefined = function(arg0) {
|
||||
const ret = arg0 === undefined;
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbindgen_json_parse = function(arg0, arg1) {
|
||||
const ret = JSON.parse(getStringFromWasm0(arg0, arg1));
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbindgen_json_serialize = function(arg0, arg1) {
|
||||
const obj = arg1;
|
||||
const ret = JSON.stringify(obj === undefined ? null : obj);
|
||||
const ptr1 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
||||
const len1 = WASM_VECTOR_LEN;
|
||||
getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
|
||||
getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
|
||||
};
|
||||
imports.wbg.__wbindgen_memory = function() {
|
||||
const ret = wasm.memory;
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbindgen_string_new = function(arg0, arg1) {
|
||||
const ret = getStringFromWasm0(arg0, arg1);
|
||||
return ret;
|
||||
};
|
||||
imports.wbg.__wbindgen_throw = function(arg0, arg1) {
|
||||
throw new Error(getStringFromWasm0(arg0, arg1));
|
||||
};
|
||||
|
||||
return imports;
|
||||
}
|
||||
|
||||
function __wbg_init_memory(imports, memory) {
|
||||
|
||||
}
|
||||
|
||||
function __wbg_finalize_init(instance, module) {
|
||||
wasm = instance.exports;
|
||||
__wbg_init.__wbindgen_wasm_module = module;
|
||||
cachedDataViewMemory0 = null;
|
||||
cachedUint8ArrayMemory0 = null;
|
||||
|
||||
|
||||
wasm.__wbindgen_start();
|
||||
return wasm;
|
||||
}
|
||||
|
||||
function initSync(module) {
|
||||
if (wasm !== undefined) return wasm;
|
||||
|
||||
|
||||
if (typeof module !== 'undefined') {
|
||||
if (Object.getPrototypeOf(module) === Object.prototype) {
|
||||
({module} = module)
|
||||
} else {
|
||||
console.warn('using deprecated parameters for `initSync()`; pass a single object instead')
|
||||
}
|
||||
}
|
||||
|
||||
const imports = __wbg_get_imports();
|
||||
|
||||
__wbg_init_memory(imports);
|
||||
|
||||
if (!(module instanceof WebAssembly.Module)) {
|
||||
module = new WebAssembly.Module(module);
|
||||
}
|
||||
|
||||
const instance = new WebAssembly.Instance(module, imports);
|
||||
|
||||
return __wbg_finalize_init(instance, module);
|
||||
}
|
||||
|
||||
async function __wbg_init(module_or_path) {
|
||||
if (wasm !== undefined) return wasm;
|
||||
|
||||
|
||||
if (typeof module_or_path !== 'undefined') {
|
||||
if (Object.getPrototypeOf(module_or_path) === Object.prototype) {
|
||||
({module_or_path} = module_or_path)
|
||||
} else {
|
||||
console.warn('using deprecated parameters for the initialization function; pass a single object instead')
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof module_or_path === 'undefined') {
|
||||
module_or_path = new URL('wasm_app_bg.wasm', import.meta.url);
|
||||
}
|
||||
const imports = __wbg_get_imports();
|
||||
|
||||
if (typeof module_or_path === 'string' || (typeof Request === 'function' && module_or_path instanceof Request) || (typeof URL === 'function' && module_or_path instanceof URL)) {
|
||||
module_or_path = fetch(module_or_path);
|
||||
}
|
||||
|
||||
__wbg_init_memory(imports);
|
||||
|
||||
const { instance, module } = await __wbg_load(await module_or_path, imports);
|
||||
|
||||
return __wbg_finalize_init(instance, module);
|
||||
}
|
||||
|
||||
export { initSync };
|
||||
export default __wbg_init;
|
BIN
crypto_vault_extension/wasm/wasm_app_bg.wasm
Normal file
BIN
crypto_vault_extension/wasm/wasm_app_bg.wasm
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user