...
This commit is contained in:
240
www/ethereum.html
Normal file
240
www/ethereum.html
Normal file
@@ -0,0 +1,240 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Ethereum WebAssembly Demo</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
.container {
|
||||
border: 1px solid #ddd;
|
||||
padding: 20px;
|
||||
border-radius: 5px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
button {
|
||||
background-color: #4CAF50;
|
||||
border: none;
|
||||
color: white;
|
||||
padding: 10px 20px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
display: inline-block;
|
||||
font-size: 16px;
|
||||
margin: 4px 2px;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
}
|
||||
button.secondary {
|
||||
background-color: #6c757d;
|
||||
}
|
||||
button.danger {
|
||||
background-color: #dc3545;
|
||||
}
|
||||
input, textarea, select {
|
||||
padding: 8px;
|
||||
margin: 5px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
width: 80%;
|
||||
}
|
||||
.result {
|
||||
margin-top: 10px;
|
||||
padding: 10px;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 4px;
|
||||
word-break: break-all;
|
||||
}
|
||||
.key-display {
|
||||
font-family: monospace;
|
||||
font-size: 12px;
|
||||
word-break: break-all;
|
||||
}
|
||||
.note {
|
||||
font-style: italic;
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
}
|
||||
.form-group {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.form-group label {
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
font-weight: bold;
|
||||
}
|
||||
.status {
|
||||
padding: 10px;
|
||||
margin-bottom: 15px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.status.logged-in {
|
||||
background-color: #d4edda;
|
||||
color: #155724;
|
||||
}
|
||||
.status.logged-out {
|
||||
background-color: #f8d7da;
|
||||
color: #721c24;
|
||||
}
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
.address-container {
|
||||
margin-top: 15px;
|
||||
padding: 10px;
|
||||
background-color: #f8f9fa;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
.address-label {
|
||||
font-weight: bold;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.address-value {
|
||||
font-family: monospace;
|
||||
word-break: break-all;
|
||||
background-color: #e9ecef;
|
||||
padding: 8px;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 10px;
|
||||
border: 1px solid #ced4da;
|
||||
}
|
||||
.nav-links {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.nav-links a {
|
||||
margin-right: 15px;
|
||||
text-decoration: none;
|
||||
color: #007bff;
|
||||
}
|
||||
.nav-links a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Ethereum WebAssembly Demo</h1>
|
||||
|
||||
<div class="nav-links">
|
||||
<a href="index.html">Main Crypto Demo</a>
|
||||
<a href="ethereum.html">Ethereum Demo</a>
|
||||
</div>
|
||||
|
||||
<!-- Login/Space Management Section -->
|
||||
<div class="container" id="login-container">
|
||||
<h2>Key Space Management</h2>
|
||||
|
||||
<div id="login-status" class="status logged-out">
|
||||
Status: Not logged in
|
||||
</div>
|
||||
|
||||
<div id="login-form">
|
||||
<div class="form-group">
|
||||
<label for="space-name">Space Name:</label>
|
||||
<input type="text" id="space-name" placeholder="Enter space name" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="space-password">Password:</label>
|
||||
<input type="password" id="space-password" placeholder="Enter password" />
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button id="login-button">Login</button>
|
||||
<button id="create-space-button">Create New Space</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="logout-form" class="hidden">
|
||||
<div class="form-group">
|
||||
<label>Current Space: <span id="current-space-name"></span></label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button id="logout-button" class="danger">Logout</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="result" id="space-result">Result will appear here</div>
|
||||
</div>
|
||||
|
||||
<!-- Keypair Management Section -->
|
||||
<div class="container" id="keypair-management-container">
|
||||
<h2>Keypair Management</h2>
|
||||
|
||||
<div id="keypair-form">
|
||||
<div class="form-group">
|
||||
<label for="keypair-name">Keypair Name:</label>
|
||||
<input type="text" id="keypair-name" placeholder="Enter keypair name" />
|
||||
<button id="create-keypair-button">Create Keypair</button>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="select-keypair">Select Keypair:</label>
|
||||
<select id="select-keypair">
|
||||
<option value="">-- Select a keypair --</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="result" id="keypair-management-result">Result will appear here</div>
|
||||
</div>
|
||||
|
||||
<!-- Ethereum Wallet Section -->
|
||||
<div class="container" id="ethereum-wallet-container">
|
||||
<h2>Ethereum Wallet</h2>
|
||||
|
||||
<div class="note">Note: All operations use the Gnosis Chain (xDAI)</div>
|
||||
|
||||
<div class="form-group">
|
||||
<button id="create-ethereum-wallet-button">Create Ethereum Wallet from Selected Keypair</button>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="wallet-name">Create from Name and Keypair:</label>
|
||||
<input type="text" id="wallet-name" placeholder="Enter name for deterministic derivation" />
|
||||
<button id="create-from-name-button">Create from Name</button>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="private-key">Import Private Key:</label>
|
||||
<input type="text" id="private-key" placeholder="Enter private key (with or without 0x prefix)" />
|
||||
<button id="import-private-key-button">Import Private Key</button>
|
||||
</div>
|
||||
|
||||
<div id="ethereum-wallet-info" class="hidden">
|
||||
<div class="address-container">
|
||||
<div class="address-label">Ethereum Address:</div>
|
||||
<div class="address-value" id="ethereum-address-value"></div>
|
||||
<button id="copy-address-button" class="secondary">Copy Address</button>
|
||||
</div>
|
||||
|
||||
<div class="address-container">
|
||||
<div class="address-label">Private Key (hex):</div>
|
||||
<div class="address-value" id="ethereum-private-key-value"></div>
|
||||
<button id="copy-private-key-button" class="secondary">Copy Private Key</button>
|
||||
<div class="note">Warning: Never share your private key with anyone!</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="result" id="ethereum-wallet-result">Result will appear here</div>
|
||||
</div>
|
||||
|
||||
<!-- Ethereum Balance Section -->
|
||||
<div class="container" id="ethereum-balance-container">
|
||||
<h2>Check Ethereum Balance</h2>
|
||||
|
||||
<div class="form-group">
|
||||
<button id="check-balance-button">Check Current Wallet Balance</button>
|
||||
</div>
|
||||
|
||||
<div class="result" id="balance-result">Balance will appear here</div>
|
||||
</div>
|
||||
|
||||
<script type="module" src="./js/ethereum.js"></script>
|
||||
</body>
|
||||
</html>
|
@@ -84,6 +84,17 @@
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
.nav-links {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
.nav-links a {
|
||||
margin-right: 15px;
|
||||
text-decoration: none;
|
||||
color: #007bff;
|
||||
}
|
||||
.nav-links a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.pubkey-container {
|
||||
margin-top: 15px;
|
||||
padding: 10px;
|
||||
@@ -109,6 +120,11 @@
|
||||
<body>
|
||||
<h1>Rust WebAssembly Crypto Example</h1>
|
||||
|
||||
<div class="nav-links">
|
||||
<a href="index.html">Main Crypto Demo</a>
|
||||
<a href="ethereum.html">Ethereum Demo</a>
|
||||
</div>
|
||||
|
||||
<!-- Login/Space Management Section -->
|
||||
<div class="container" id="login-container">
|
||||
<h2>Key Space Management</h2>
|
||||
|
528
www/js/ethereum.js
Normal file
528
www/js/ethereum.js
Normal file
@@ -0,0 +1,528 @@
|
||||
// Import our WebAssembly module
|
||||
import init, {
|
||||
create_key_space,
|
||||
encrypt_key_space,
|
||||
decrypt_key_space,
|
||||
logout,
|
||||
create_keypair,
|
||||
select_keypair,
|
||||
list_keypairs,
|
||||
keypair_pub_key,
|
||||
create_ethereum_wallet,
|
||||
create_ethereum_wallet_from_name,
|
||||
create_ethereum_wallet_from_private_key,
|
||||
get_ethereum_address,
|
||||
get_ethereum_private_key,
|
||||
format_eth_balance,
|
||||
clear_ethereum_wallets
|
||||
} from '../../pkg/webassembly.js';
|
||||
|
||||
// Helper function to convert ArrayBuffer to hex string
|
||||
function bufferToHex(buffer) {
|
||||
return Array.from(new Uint8Array(buffer))
|
||||
.map(b => b.toString(16).padStart(2, '0'))
|
||||
.join('');
|
||||
}
|
||||
|
||||
// Helper function to convert hex string to Uint8Array
|
||||
function hexToBuffer(hex) {
|
||||
const bytes = new Uint8Array(hex.length / 2);
|
||||
for (let i = 0; i < hex.length; i += 2) {
|
||||
bytes[i / 2] = parseInt(hex.substr(i, 2), 16);
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
// LocalStorage functions for key spaces
|
||||
const STORAGE_PREFIX = 'crypto_space_';
|
||||
const ETH_WALLET_PREFIX = 'eth_wallet_';
|
||||
|
||||
// Save encrypted space to localStorage
|
||||
function saveSpaceToStorage(spaceName, encryptedData) {
|
||||
localStorage.setItem(`${STORAGE_PREFIX}${spaceName}`, encryptedData);
|
||||
}
|
||||
|
||||
// Get encrypted space from localStorage
|
||||
function getSpaceFromStorage(spaceName) {
|
||||
return localStorage.getItem(`${STORAGE_PREFIX}${spaceName}`);
|
||||
}
|
||||
|
||||
// Save Ethereum wallet to localStorage
|
||||
function saveEthWalletToStorage(address, privateKey) {
|
||||
localStorage.setItem(`${ETH_WALLET_PREFIX}${address}`, privateKey);
|
||||
}
|
||||
|
||||
// Get Ethereum wallet from localStorage
|
||||
function getEthWalletFromStorage(address) {
|
||||
return localStorage.getItem(`${ETH_WALLET_PREFIX}${address}`);
|
||||
}
|
||||
|
||||
// Session state
|
||||
let isLoggedIn = false;
|
||||
let currentSpace = null;
|
||||
let selectedKeypair = null;
|
||||
let hasEthereumWallet = false;
|
||||
|
||||
// Update UI based on login state
|
||||
function updateLoginUI() {
|
||||
const loginForm = document.getElementById('login-form');
|
||||
const logoutForm = document.getElementById('logout-form');
|
||||
const loginStatus = document.getElementById('login-status');
|
||||
const currentSpaceName = document.getElementById('current-space-name');
|
||||
|
||||
if (isLoggedIn) {
|
||||
loginForm.classList.add('hidden');
|
||||
logoutForm.classList.remove('hidden');
|
||||
loginStatus.textContent = 'Status: Logged in';
|
||||
loginStatus.className = 'status logged-in';
|
||||
currentSpaceName.textContent = currentSpace;
|
||||
} else {
|
||||
loginForm.classList.remove('hidden');
|
||||
logoutForm.classList.add('hidden');
|
||||
loginStatus.textContent = 'Status: Not logged in';
|
||||
loginStatus.className = 'status logged-out';
|
||||
currentSpaceName.textContent = '';
|
||||
|
||||
// Hide Ethereum wallet info when logged out
|
||||
document.getElementById('ethereum-wallet-info').classList.add('hidden');
|
||||
hasEthereumWallet = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Update the keypairs dropdown list
|
||||
function updateKeypairsList() {
|
||||
const selectKeypair = document.getElementById('select-keypair');
|
||||
|
||||
// Clear existing options
|
||||
while (selectKeypair.options.length > 1) {
|
||||
selectKeypair.remove(1);
|
||||
}
|
||||
|
||||
try {
|
||||
// Get keypairs list
|
||||
const keypairs = list_keypairs();
|
||||
|
||||
// Add options for each keypair
|
||||
keypairs.forEach(keypairName => {
|
||||
const option = document.createElement('option');
|
||||
option.value = keypairName;
|
||||
option.textContent = keypairName;
|
||||
selectKeypair.appendChild(option);
|
||||
});
|
||||
|
||||
// If there's a selected keypair, select it in the dropdown
|
||||
if (selectedKeypair) {
|
||||
selectKeypair.value = selectedKeypair;
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error updating keypairs list:', e);
|
||||
}
|
||||
}
|
||||
|
||||
// Login to a space
|
||||
async function performLogin() {
|
||||
const spaceName = document.getElementById('space-name').value.trim();
|
||||
const password = document.getElementById('space-password').value;
|
||||
|
||||
if (!spaceName || !password) {
|
||||
document.getElementById('space-result').textContent = 'Please enter both space name and password';
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Get encrypted space from localStorage
|
||||
const encryptedSpace = getSpaceFromStorage(spaceName);
|
||||
if (!encryptedSpace) {
|
||||
document.getElementById('space-result').textContent = `Space "${spaceName}" not found`;
|
||||
return;
|
||||
}
|
||||
|
||||
// Decrypt the space
|
||||
const result = decrypt_key_space(encryptedSpace, password);
|
||||
if (result === 0) {
|
||||
isLoggedIn = true;
|
||||
currentSpace = spaceName;
|
||||
updateLoginUI();
|
||||
updateKeypairsList();
|
||||
document.getElementById('space-result').textContent = `Successfully logged in to space "${spaceName}"`;
|
||||
} else {
|
||||
document.getElementById('space-result').textContent = `Error logging in: ${result}`;
|
||||
}
|
||||
} catch (e) {
|
||||
document.getElementById('space-result').textContent = `Error: ${e}`;
|
||||
}
|
||||
}
|
||||
|
||||
// Create a new space
|
||||
async function performCreateSpace() {
|
||||
const spaceName = document.getElementById('space-name').value.trim();
|
||||
const password = document.getElementById('space-password').value;
|
||||
|
||||
if (!spaceName || !password) {
|
||||
document.getElementById('space-result').textContent = 'Please enter both space name and password';
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if space already exists
|
||||
if (getSpaceFromStorage(spaceName)) {
|
||||
document.getElementById('space-result').textContent = `Space "${spaceName}" already exists`;
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Create new space
|
||||
const result = create_key_space(spaceName);
|
||||
if (result === 0) {
|
||||
// Encrypt and save the space
|
||||
const encryptedSpace = encrypt_key_space(password);
|
||||
saveSpaceToStorage(spaceName, encryptedSpace);
|
||||
|
||||
isLoggedIn = true;
|
||||
currentSpace = spaceName;
|
||||
updateLoginUI();
|
||||
updateKeypairsList();
|
||||
document.getElementById('space-result').textContent = `Successfully created space "${spaceName}"`;
|
||||
} else {
|
||||
document.getElementById('space-result').textContent = `Error creating space: ${result}`;
|
||||
}
|
||||
} catch (e) {
|
||||
document.getElementById('space-result').textContent = `Error: ${e}`;
|
||||
}
|
||||
}
|
||||
|
||||
// Logout from current space
|
||||
function performLogout() {
|
||||
logout();
|
||||
clear_ethereum_wallets();
|
||||
isLoggedIn = false;
|
||||
currentSpace = null;
|
||||
selectedKeypair = null;
|
||||
hasEthereumWallet = false;
|
||||
updateLoginUI();
|
||||
document.getElementById('space-result').textContent = 'Logged out successfully';
|
||||
}
|
||||
|
||||
// Create a new keypair
|
||||
async function performCreateKeypair() {
|
||||
if (!isLoggedIn) {
|
||||
document.getElementById('keypair-management-result').textContent = 'Please login first';
|
||||
return;
|
||||
}
|
||||
|
||||
const keypairName = document.getElementById('keypair-name').value.trim();
|
||||
|
||||
if (!keypairName) {
|
||||
document.getElementById('keypair-management-result').textContent = 'Please enter a keypair name';
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Create new keypair
|
||||
const result = create_keypair(keypairName);
|
||||
if (result === 0) {
|
||||
document.getElementById('keypair-management-result').textContent = `Successfully created keypair "${keypairName}"`;
|
||||
|
||||
// Update keypairs list
|
||||
updateKeypairsList();
|
||||
|
||||
// Select the new keypair
|
||||
selectedKeypair = keypairName;
|
||||
document.getElementById('select-keypair').value = keypairName;
|
||||
|
||||
// Save the updated space to localStorage
|
||||
saveCurrentSpace();
|
||||
} else {
|
||||
document.getElementById('keypair-management-result').textContent = `Error creating keypair: ${result}`;
|
||||
}
|
||||
} catch (e) {
|
||||
document.getElementById('keypair-management-result').textContent = `Error: ${e}`;
|
||||
}
|
||||
}
|
||||
|
||||
// Select a keypair
|
||||
async function performSelectKeypair() {
|
||||
if (!isLoggedIn) {
|
||||
document.getElementById('keypair-management-result').textContent = 'Please login first';
|
||||
return;
|
||||
}
|
||||
|
||||
const keypairName = document.getElementById('select-keypair').value;
|
||||
|
||||
if (!keypairName) {
|
||||
document.getElementById('keypair-management-result').textContent = 'Please select a keypair';
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Select keypair
|
||||
const result = select_keypair(keypairName);
|
||||
if (result === 0) {
|
||||
selectedKeypair = keypairName;
|
||||
document.getElementById('keypair-management-result').textContent = `Selected keypair "${keypairName}"`;
|
||||
|
||||
// Hide Ethereum wallet info when changing keypairs
|
||||
document.getElementById('ethereum-wallet-info').classList.add('hidden');
|
||||
hasEthereumWallet = false;
|
||||
} else {
|
||||
document.getElementById('keypair-management-result').textContent = `Error selecting keypair: ${result}`;
|
||||
}
|
||||
} catch (e) {
|
||||
document.getElementById('keypair-management-result').textContent = `Error: ${e}`;
|
||||
}
|
||||
}
|
||||
|
||||
// Save the current space to localStorage
|
||||
function saveCurrentSpace() {
|
||||
if (!isLoggedIn || !currentSpace) return;
|
||||
|
||||
try {
|
||||
const password = document.getElementById('space-password').value;
|
||||
if (!password) {
|
||||
console.error('Password not available for saving space');
|
||||
return;
|
||||
}
|
||||
|
||||
const encryptedSpace = encrypt_key_space(password);
|
||||
saveSpaceToStorage(currentSpace, encryptedSpace);
|
||||
} catch (e) {
|
||||
console.error('Error saving space:', e);
|
||||
}
|
||||
}
|
||||
|
||||
// Create an Ethereum wallet from the selected keypair
|
||||
async function performCreateEthereumWallet() {
|
||||
if (!isLoggedIn) {
|
||||
document.getElementById('ethereum-wallet-result').textContent = 'Please login first';
|
||||
return;
|
||||
}
|
||||
|
||||
if (!selectedKeypair) {
|
||||
document.getElementById('ethereum-wallet-result').textContent = 'Please select a keypair first';
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Create Ethereum wallet
|
||||
const result = create_ethereum_wallet();
|
||||
if (result === 0) {
|
||||
hasEthereumWallet = true;
|
||||
|
||||
// Get and display Ethereum address
|
||||
const address = get_ethereum_address();
|
||||
document.getElementById('ethereum-address-value').textContent = address;
|
||||
|
||||
// Get and display private key
|
||||
const privateKey = get_ethereum_private_key();
|
||||
document.getElementById('ethereum-private-key-value').textContent = privateKey;
|
||||
|
||||
// Show the wallet info
|
||||
document.getElementById('ethereum-wallet-info').classList.remove('hidden');
|
||||
|
||||
// Save the wallet to localStorage
|
||||
saveEthWalletToStorage(address, privateKey);
|
||||
|
||||
document.getElementById('ethereum-wallet-result').textContent = 'Successfully created Ethereum wallet';
|
||||
|
||||
// Save the updated space to localStorage
|
||||
saveCurrentSpace();
|
||||
} else {
|
||||
document.getElementById('ethereum-wallet-result').textContent = `Error creating Ethereum wallet: ${result}`;
|
||||
}
|
||||
} catch (e) {
|
||||
document.getElementById('ethereum-wallet-result').textContent = `Error: ${e}`;
|
||||
}
|
||||
}
|
||||
|
||||
// Create an Ethereum wallet from a name and the selected keypair
|
||||
async function performCreateEthereumWalletFromName() {
|
||||
if (!isLoggedIn) {
|
||||
document.getElementById('ethereum-wallet-result').textContent = 'Please login first';
|
||||
return;
|
||||
}
|
||||
|
||||
if (!selectedKeypair) {
|
||||
document.getElementById('ethereum-wallet-result').textContent = 'Please select a keypair first';
|
||||
return;
|
||||
}
|
||||
|
||||
const name = document.getElementById('wallet-name').value.trim();
|
||||
|
||||
if (!name) {
|
||||
document.getElementById('ethereum-wallet-result').textContent = 'Please enter a name for derivation';
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Create Ethereum wallet from name
|
||||
const result = create_ethereum_wallet_from_name(name);
|
||||
if (result === 0) {
|
||||
hasEthereumWallet = true;
|
||||
|
||||
// Get and display Ethereum address
|
||||
const address = get_ethereum_address();
|
||||
document.getElementById('ethereum-address-value').textContent = address;
|
||||
|
||||
// Get and display private key
|
||||
const privateKey = get_ethereum_private_key();
|
||||
document.getElementById('ethereum-private-key-value').textContent = privateKey;
|
||||
|
||||
// Show the wallet info
|
||||
document.getElementById('ethereum-wallet-info').classList.remove('hidden');
|
||||
|
||||
// Save the wallet to localStorage
|
||||
saveEthWalletToStorage(address, privateKey);
|
||||
|
||||
document.getElementById('ethereum-wallet-result').textContent = `Successfully created Ethereum wallet from name "${name}"`;
|
||||
|
||||
// Save the updated space to localStorage
|
||||
saveCurrentSpace();
|
||||
} else {
|
||||
document.getElementById('ethereum-wallet-result').textContent = `Error creating Ethereum wallet: ${result}`;
|
||||
}
|
||||
} catch (e) {
|
||||
document.getElementById('ethereum-wallet-result').textContent = `Error: ${e}`;
|
||||
}
|
||||
}
|
||||
|
||||
// Create an Ethereum wallet from a private key
|
||||
async function performCreateEthereumWalletFromPrivateKey() {
|
||||
if (!isLoggedIn) {
|
||||
document.getElementById('ethereum-wallet-result').textContent = 'Please login first';
|
||||
return;
|
||||
}
|
||||
|
||||
const privateKey = document.getElementById('private-key').value.trim();
|
||||
|
||||
if (!privateKey) {
|
||||
document.getElementById('ethereum-wallet-result').textContent = 'Please enter a private key';
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Create Ethereum wallet from private key
|
||||
const result = create_ethereum_wallet_from_private_key(privateKey);
|
||||
if (result === 0) {
|
||||
hasEthereumWallet = true;
|
||||
|
||||
// Get and display Ethereum address
|
||||
const address = get_ethereum_address();
|
||||
document.getElementById('ethereum-address-value').textContent = address;
|
||||
|
||||
// Get and display private key
|
||||
const displayPrivateKey = get_ethereum_private_key();
|
||||
document.getElementById('ethereum-private-key-value').textContent = displayPrivateKey;
|
||||
|
||||
// Show the wallet info
|
||||
document.getElementById('ethereum-wallet-info').classList.remove('hidden');
|
||||
|
||||
// Save the wallet to localStorage
|
||||
saveEthWalletToStorage(address, displayPrivateKey);
|
||||
|
||||
document.getElementById('ethereum-wallet-result').textContent = 'Successfully imported Ethereum wallet from private key';
|
||||
|
||||
// Save the updated space to localStorage
|
||||
saveCurrentSpace();
|
||||
} else {
|
||||
document.getElementById('ethereum-wallet-result').textContent = `Error importing Ethereum wallet: ${result}`;
|
||||
}
|
||||
} catch (e) {
|
||||
document.getElementById('ethereum-wallet-result').textContent = `Error: ${e}`;
|
||||
}
|
||||
}
|
||||
|
||||
// Check the balance of an Ethereum address
|
||||
async function checkBalance() {
|
||||
if (!hasEthereumWallet) {
|
||||
document.getElementById('balance-result').textContent = 'Please create an Ethereum wallet first';
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const address = get_ethereum_address();
|
||||
|
||||
document.getElementById('balance-result').textContent = 'Checking balance...';
|
||||
|
||||
// Use the Ethereum Web3 API directly from JavaScript
|
||||
const response = await fetch(GNOSIS_RPC_URL, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
jsonrpc: '2.0',
|
||||
method: 'eth_getBalance',
|
||||
params: [address, 'latest'],
|
||||
id: 1,
|
||||
}),
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.error) {
|
||||
document.getElementById('balance-result').textContent = `Error: ${data.error.message}`;
|
||||
return;
|
||||
}
|
||||
|
||||
const balanceHex = data.result;
|
||||
const formattedBalance = format_eth_balance(balanceHex);
|
||||
|
||||
document.getElementById('balance-result').textContent = `Balance: ${formattedBalance}`;
|
||||
} catch (e) {
|
||||
document.getElementById('balance-result').textContent = `Error: ${e}`;
|
||||
}
|
||||
}
|
||||
|
||||
// Copy text to clipboard
|
||||
function copyToClipboard(text, successMessage) {
|
||||
navigator.clipboard.writeText(text)
|
||||
.then(() => {
|
||||
alert(successMessage);
|
||||
})
|
||||
.catch(err => {
|
||||
console.error('Could not copy text: ', err);
|
||||
});
|
||||
}
|
||||
|
||||
// Constants
|
||||
const GNOSIS_RPC_URL = "https://rpc.gnosis.gateway.fm";
|
||||
const GNOSIS_EXPLORER = "https://gnosisscan.io";
|
||||
|
||||
async function run() {
|
||||
// Initialize the WebAssembly module
|
||||
await init();
|
||||
|
||||
console.log('WebAssembly crypto module initialized!');
|
||||
|
||||
// Set up the login/space management
|
||||
document.getElementById('login-button').addEventListener('click', performLogin);
|
||||
document.getElementById('create-space-button').addEventListener('click', performCreateSpace);
|
||||
document.getElementById('logout-button').addEventListener('click', performLogout);
|
||||
|
||||
// Set up the keypair management
|
||||
document.getElementById('create-keypair-button').addEventListener('click', performCreateKeypair);
|
||||
document.getElementById('select-keypair').addEventListener('change', performSelectKeypair);
|
||||
|
||||
// Set up the Ethereum wallet management
|
||||
document.getElementById('create-ethereum-wallet-button').addEventListener('click', performCreateEthereumWallet);
|
||||
document.getElementById('create-from-name-button').addEventListener('click', performCreateEthereumWalletFromName);
|
||||
document.getElementById('import-private-key-button').addEventListener('click', performCreateEthereumWalletFromPrivateKey);
|
||||
|
||||
// Set up the copy buttons
|
||||
document.getElementById('copy-address-button').addEventListener('click', () => {
|
||||
const address = document.getElementById('ethereum-address-value').textContent;
|
||||
copyToClipboard(address, 'Ethereum address copied to clipboard!');
|
||||
});
|
||||
|
||||
document.getElementById('copy-private-key-button').addEventListener('click', () => {
|
||||
const privateKey = document.getElementById('ethereum-private-key-value').textContent;
|
||||
copyToClipboard(privateKey, 'Private key copied to clipboard!');
|
||||
});
|
||||
|
||||
// Set up the balance check
|
||||
document.getElementById('check-balance-button').addEventListener('click', checkBalance);
|
||||
|
||||
// Initialize UI
|
||||
updateLoginUI();
|
||||
}
|
||||
|
||||
run().catch(console.error);
|
Reference in New Issue
Block a user