All checks were successful
check / check (push) Successful in 14s
vault.js: Argon2id key derivation + XSalsa20-Poly1305 encryption via libsodium-wrappers-sumo. No raw crypto primitives. Wallet creation now requires a password. The mnemonic or private key is encrypted before storage — only the ciphertext blob (salt, nonce, ciphertext) is persisted. The plaintext secret is never stored. Sending requires the password to decrypt the secret, derive the signing key, and construct the transaction. Wrong password is caught and reported.
478 lines
20 KiB
HTML
478 lines
20 KiB
HTML
<!doctype html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<title>AutistMask</title>
|
|
<link rel="stylesheet" href="styles.css" />
|
|
</head>
|
|
<body class="bg-bg text-fg font-mono text-sm">
|
|
<div id="app" class="p-2">
|
|
<!-- ============ WELCOME / FIRST USE ============ -->
|
|
<div id="view-welcome" class="view hidden">
|
|
<h1 class="font-bold border-b border-border pb-1 mb-3">
|
|
Welcome to AutistMask
|
|
</h1>
|
|
<p class="mb-3">To get started, add a wallet.</p>
|
|
<button
|
|
id="btn-welcome-add"
|
|
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
|
|
>
|
|
Add wallet
|
|
</button>
|
|
</div>
|
|
|
|
<!-- ============ ADD WALLET (unified create/import) ============ -->
|
|
<div id="view-add-wallet" class="view hidden">
|
|
<h1 class="font-bold border-b border-border pb-1 mb-3">
|
|
Add Wallet
|
|
</h1>
|
|
<p class="mb-2">
|
|
Enter your 12 or 24 word recovery phrase below, or click the
|
|
button to roll the die for a new one.
|
|
</p>
|
|
<div class="mb-1 flex justify-end">
|
|
<button
|
|
id="btn-generate-phrase"
|
|
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer text-xs"
|
|
title="Generate a random recovery phrase"
|
|
>
|
|
[⚀]
|
|
</button>
|
|
</div>
|
|
<div class="mb-2">
|
|
<textarea
|
|
id="wallet-mnemonic"
|
|
rows="3"
|
|
class="border border-border p-1 w-full font-mono text-sm bg-bg text-fg resize-y"
|
|
placeholder="word word word ..."
|
|
></textarea>
|
|
</div>
|
|
<div
|
|
id="add-wallet-phrase-warning"
|
|
class="text-xs mb-2 border border-border border-dashed p-2 hidden"
|
|
>
|
|
These words are your recovery phrase. Write them down on
|
|
paper and keep them somewhere safe. Anyone with these words
|
|
can access your funds. If you lose them, your wallet cannot
|
|
be recovered.
|
|
</div>
|
|
<div class="mb-2" id="add-wallet-password-section">
|
|
<label class="block mb-1">Choose a password</label>
|
|
<p class="text-xs text-muted mb-1">
|
|
This password encrypts your recovery phrase on this
|
|
device. You will need it to send funds.
|
|
</p>
|
|
<input
|
|
type="password"
|
|
id="add-wallet-password"
|
|
class="border border-border p-1 w-full font-mono text-sm bg-bg text-fg"
|
|
/>
|
|
</div>
|
|
<div class="mb-2" id="add-wallet-password-confirm-section">
|
|
<label class="block mb-1">Confirm password</label>
|
|
<input
|
|
type="password"
|
|
id="add-wallet-password-confirm"
|
|
class="border border-border p-1 w-full font-mono text-sm bg-bg text-fg"
|
|
/>
|
|
</div>
|
|
<div class="flex gap-2">
|
|
<button
|
|
id="btn-add-wallet-confirm"
|
|
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
|
|
>
|
|
Add
|
|
</button>
|
|
<button
|
|
id="btn-add-wallet-back"
|
|
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
|
|
>
|
|
Back
|
|
</button>
|
|
</div>
|
|
<div
|
|
id="add-wallet-error"
|
|
class="mt-2 border border-border border-dashed p-1 hidden"
|
|
></div>
|
|
<div class="mt-3 text-xs text-muted">
|
|
Have a private key instead?
|
|
<button
|
|
id="btn-add-wallet-import-key"
|
|
class="underline cursor-pointer bg-transparent border-none text-fg text-xs font-mono p-0"
|
|
>
|
|
Import private key
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ============ IMPORT PRIVATE KEY ============ -->
|
|
<div id="view-import-key" class="view hidden">
|
|
<h1 class="font-bold border-b border-border pb-1 mb-3">
|
|
Import Private Key
|
|
</h1>
|
|
<p class="mb-2">
|
|
Paste your private key below. This wallet will have a single
|
|
address.
|
|
</p>
|
|
<div class="mb-2">
|
|
<input
|
|
type="password"
|
|
id="import-private-key"
|
|
class="border border-border p-1 w-full font-mono text-sm bg-bg text-fg"
|
|
placeholder="0x..."
|
|
/>
|
|
</div>
|
|
<div class="mb-2" id="import-key-password-section">
|
|
<label class="block mb-1">Choose a password</label>
|
|
<p class="text-xs text-muted mb-1">
|
|
This password encrypts your private key on this device.
|
|
You will need it to send funds.
|
|
</p>
|
|
<input
|
|
type="password"
|
|
id="import-key-password"
|
|
class="border border-border p-1 w-full font-mono text-sm bg-bg text-fg"
|
|
/>
|
|
</div>
|
|
<div class="mb-2" id="import-key-password-confirm-section">
|
|
<label class="block mb-1">Confirm password</label>
|
|
<input
|
|
type="password"
|
|
id="import-key-password-confirm"
|
|
class="border border-border p-1 w-full font-mono text-sm bg-bg text-fg"
|
|
/>
|
|
</div>
|
|
<div class="flex gap-2">
|
|
<button
|
|
id="btn-import-key-confirm"
|
|
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
|
|
>
|
|
Import
|
|
</button>
|
|
<button
|
|
id="btn-import-key-back"
|
|
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
|
|
>
|
|
Back
|
|
</button>
|
|
</div>
|
|
<div
|
|
id="import-key-error"
|
|
class="mt-2 border border-border border-dashed p-1 hidden"
|
|
></div>
|
|
</div>
|
|
|
|
<!-- ============ MAIN VIEW: ALL WALLETS & ADDRESSES ============ -->
|
|
<div id="view-main" class="view hidden">
|
|
<div
|
|
class="flex justify-between items-center border-b border-border pb-1 mb-2"
|
|
>
|
|
<h1 class="font-bold">AutistMask</h1>
|
|
<button
|
|
id="btn-settings"
|
|
class="border border-border px-1 hover:bg-fg hover:text-bg cursor-pointer"
|
|
title="Settings"
|
|
>
|
|
Settings
|
|
</button>
|
|
</div>
|
|
|
|
<!-- wallet list -->
|
|
<div id="wallet-list"></div>
|
|
|
|
<!-- add wallet button -->
|
|
<div class="mt-3 border-t border-border pt-2">
|
|
<button
|
|
id="btn-main-add-wallet"
|
|
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
|
|
>
|
|
+ Add wallet
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ============ ADDRESS DETAIL VIEW ============ -->
|
|
<div id="view-address" class="view hidden">
|
|
<div
|
|
class="flex justify-between items-center border-b border-border pb-1 mb-2"
|
|
>
|
|
<h1 class="font-bold" id="address-title">Address</h1>
|
|
<button
|
|
id="btn-address-back"
|
|
class="border border-border px-1 hover:bg-fg hover:text-bg cursor-pointer"
|
|
>
|
|
Back
|
|
</button>
|
|
</div>
|
|
|
|
<div id="address-ens" class="font-bold mb-1 hidden"></div>
|
|
<div
|
|
id="address-full"
|
|
class="text-xs break-all mb-1 cursor-pointer"
|
|
title="Click to copy"
|
|
></div>
|
|
<div
|
|
class="text-xs text-muted mb-3"
|
|
id="address-copied-msg"
|
|
></div>
|
|
|
|
<!-- balance -->
|
|
<div class="border-b border-border-light pb-2 mb-2">
|
|
<div class="text-base font-bold">
|
|
<span id="address-eth-balance">0.0000</span> ETH
|
|
</div>
|
|
<div
|
|
class="text-xs text-muted"
|
|
id="address-usd-value"
|
|
></div>
|
|
</div>
|
|
|
|
<!-- actions -->
|
|
<div class="flex gap-2 mb-3">
|
|
<button
|
|
id="btn-send"
|
|
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer flex-1"
|
|
>
|
|
Send
|
|
</button>
|
|
<button
|
|
id="btn-receive"
|
|
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer flex-1"
|
|
>
|
|
Receive
|
|
</button>
|
|
</div>
|
|
|
|
<!-- tokens -->
|
|
<div>
|
|
<div
|
|
class="flex justify-between items-center border-b border-border pb-1 mb-1"
|
|
>
|
|
<h2 class="font-bold">Tokens</h2>
|
|
<button
|
|
id="btn-add-token"
|
|
class="border border-border px-1 hover:bg-fg hover:text-bg cursor-pointer text-xs"
|
|
>
|
|
+ Add
|
|
</button>
|
|
</div>
|
|
<div id="token-list">
|
|
<div class="text-muted text-xs py-1">
|
|
No tokens added yet. Use "+ Add" to track a token.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ============ SEND ============ -->
|
|
<div id="view-send" class="view hidden">
|
|
<h1 class="font-bold border-b border-border pb-1 mb-3">Send</h1>
|
|
<div class="mb-2">
|
|
<label class="block mb-1">What to send</label>
|
|
<select
|
|
id="send-token"
|
|
class="border border-border p-1 w-full font-mono text-sm bg-bg text-fg"
|
|
>
|
|
<option value="ETH">ETH</option>
|
|
</select>
|
|
</div>
|
|
<div class="mb-2">
|
|
<label class="block mb-1">To</label>
|
|
<input
|
|
type="text"
|
|
id="send-to"
|
|
class="border border-border p-1 w-full font-mono text-sm bg-bg text-fg"
|
|
placeholder="Address (0x...) or ENS name"
|
|
/>
|
|
</div>
|
|
<div class="mb-2">
|
|
<label class="block mb-1">Amount</label>
|
|
<input
|
|
type="text"
|
|
id="send-amount"
|
|
class="border border-border p-1 w-full font-mono text-sm bg-bg text-fg"
|
|
placeholder="0.0"
|
|
/>
|
|
</div>
|
|
<div
|
|
id="send-fee-estimate"
|
|
class="text-xs text-muted mb-2 hidden"
|
|
></div>
|
|
<div class="mb-2">
|
|
<label class="block mb-1">Password</label>
|
|
<p class="text-xs text-muted mb-1">
|
|
Required to authorize the transaction.
|
|
</p>
|
|
<input
|
|
type="password"
|
|
id="send-password"
|
|
class="border border-border p-1 w-full font-mono text-sm bg-bg text-fg"
|
|
/>
|
|
</div>
|
|
<div class="flex gap-2">
|
|
<button
|
|
id="btn-send-confirm"
|
|
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
|
|
>
|
|
Send
|
|
</button>
|
|
<button
|
|
id="btn-send-back"
|
|
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
|
|
>
|
|
Cancel
|
|
</button>
|
|
</div>
|
|
<div
|
|
id="send-status"
|
|
class="mt-2 border border-border p-1 hidden"
|
|
></div>
|
|
</div>
|
|
|
|
<!-- ============ RECEIVE ============ -->
|
|
<div id="view-receive" class="view hidden">
|
|
<h1 class="font-bold border-b border-border pb-1 mb-3">
|
|
Receive
|
|
</h1>
|
|
<p class="mb-2">
|
|
Share this address with the sender. Make sure you only use
|
|
this address to receive Ethereum tokens.
|
|
</p>
|
|
<div class="flex justify-center mb-3">
|
|
<canvas id="receive-qr"></canvas>
|
|
</div>
|
|
<div
|
|
id="receive-address"
|
|
class="border border-border p-2 break-all select-all mb-3"
|
|
></div>
|
|
<div class="flex gap-2">
|
|
<button
|
|
id="btn-receive-copy"
|
|
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
|
|
>
|
|
Copy address
|
|
</button>
|
|
<button
|
|
id="btn-receive-back"
|
|
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
|
|
>
|
|
Back
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ============ ADD TOKEN ============ -->
|
|
<div id="view-add-token" class="view hidden">
|
|
<h1 class="font-bold border-b border-border pb-1 mb-3">
|
|
Add Token
|
|
</h1>
|
|
<p class="mb-2">
|
|
Enter the contract address of the token you want to track.
|
|
You can find this on the token's page on Etherscan.
|
|
</p>
|
|
<div class="mb-2">
|
|
<label class="block mb-1">Contract address</label>
|
|
<input
|
|
type="text"
|
|
id="add-token-address"
|
|
class="border border-border p-1 w-full font-mono text-sm bg-bg text-fg"
|
|
placeholder="0x..."
|
|
/>
|
|
</div>
|
|
<div
|
|
id="add-token-info"
|
|
class="text-xs text-muted mb-2 hidden"
|
|
></div>
|
|
<div class="flex gap-2">
|
|
<button
|
|
id="btn-add-token-confirm"
|
|
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
|
|
>
|
|
Add
|
|
</button>
|
|
<button
|
|
id="btn-add-token-back"
|
|
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
|
|
>
|
|
Cancel
|
|
</button>
|
|
</div>
|
|
<div
|
|
id="add-token-error"
|
|
class="mt-2 border border-border border-dashed p-1 hidden"
|
|
></div>
|
|
</div>
|
|
|
|
<!-- ============ SETTINGS ============ -->
|
|
<div id="view-settings" class="view hidden">
|
|
<h1 class="font-bold border-b border-border pb-1 mb-3">
|
|
Settings
|
|
</h1>
|
|
|
|
<h2 class="font-bold mb-1">Network</h2>
|
|
<p class="text-xs text-muted mb-1">
|
|
The server used to talk to the Ethereum network. Change this
|
|
if you run your own node or prefer a different provider.
|
|
</p>
|
|
<div class="mb-3">
|
|
<input
|
|
type="text"
|
|
id="settings-rpc"
|
|
class="border border-border p-1 w-full font-mono text-sm bg-bg text-fg"
|
|
/>
|
|
<button
|
|
id="btn-save-rpc"
|
|
class="border border-border px-2 py-1 mt-1 hover:bg-fg hover:text-bg cursor-pointer"
|
|
>
|
|
Save
|
|
</button>
|
|
</div>
|
|
|
|
<div class="border-t border-border pt-2">
|
|
<button
|
|
id="btn-settings-back"
|
|
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
|
|
>
|
|
Back
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ============ APPROVAL ============ -->
|
|
<div id="view-approve" class="view hidden">
|
|
<h1 class="font-bold border-b border-border pb-1 mb-3">
|
|
A website is requesting access
|
|
</h1>
|
|
<div class="mb-2">
|
|
<div class="text-xs text-muted mb-1">
|
|
From:
|
|
<span id="approve-origin" class="font-bold"></span>
|
|
</div>
|
|
<div class="font-bold mb-1" id="approve-type"></div>
|
|
</div>
|
|
<pre
|
|
id="approve-details"
|
|
class="border border-border p-2 text-xs overflow-auto mb-3 max-h-64"
|
|
></pre>
|
|
<div class="flex gap-2">
|
|
<button
|
|
id="btn-approve"
|
|
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
|
|
>
|
|
Allow
|
|
</button>
|
|
<button
|
|
id="btn-reject"
|
|
class="border border-border px-2 py-1 hover:bg-fg hover:text-bg cursor-pointer"
|
|
>
|
|
Deny
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="index.js"></script>
|
|
</body>
|
|
</html>
|