-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #19 from cr0bar/main
NSD Phoenix Edition
- Loading branch information
Showing
52 changed files
with
8,477 additions
and
589 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,366 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | ||
<title>Nostr Signing Device Configuration Tool</title> | ||
<style> | ||
body { | ||
font-family: Arial, sans-serif; | ||
margin: 0; | ||
padding: 0; | ||
background-color: #f4f4f9; | ||
color: #333; | ||
} | ||
|
||
header { | ||
background-color: #6200ea; | ||
color: white; | ||
padding: 10px 20px; | ||
text-align: center; | ||
} | ||
|
||
main { | ||
padding: 20px; | ||
width: 1000px; | ||
margin: 0 auto; | ||
} | ||
|
||
h1 { | ||
color: #ffffff; | ||
} | ||
|
||
h2 { | ||
color: #6200ea; | ||
} | ||
|
||
div { | ||
margin-bottom: 20px; | ||
} | ||
|
||
label { | ||
font-weight: bold; | ||
display: block; | ||
margin-bottom: 5px; | ||
color: #6200ea; | ||
} | ||
|
||
select, input[type="text"], input[type="password"], button { | ||
width: 100%; | ||
padding: 10px; | ||
margin-bottom: 10px; | ||
border: 1px solid #ccc; | ||
border-radius: 4px; | ||
box-sizing: border-box; | ||
} | ||
|
||
button { | ||
background-color: #6200ea; | ||
color: white; | ||
border: none; | ||
cursor: pointer; | ||
} | ||
|
||
button:hover { | ||
background-color: #4500b5; | ||
} | ||
|
||
#output { | ||
background: #fff; | ||
border: 1px solid #ccc; | ||
padding: 10px; | ||
border-radius: 4px; | ||
max-height: 300px; | ||
overflow-y: auto; | ||
} | ||
|
||
table { | ||
width: 100%; | ||
border-collapse: collapse; | ||
margin-top: 20px; | ||
} | ||
|
||
table, th, td { | ||
border: 1px solid #ccc; | ||
} | ||
|
||
th, td { | ||
padding: 10px; | ||
text-align: left; | ||
} | ||
|
||
th { | ||
background-color: #6200ea; | ||
color: white; | ||
} | ||
|
||
td { | ||
background-color: #f9f9f9; | ||
} | ||
</style> | ||
</head> | ||
<body> | ||
<header> | ||
<h1>Nostr Signing Device Configuration Tool</h1> | ||
</header> | ||
<main> | ||
<div> | ||
<button id="connectDevice">Connect to Device</button> | ||
<button id="disconnectDevice">Disconnect</button> | ||
</div> | ||
|
||
<div> | ||
<label for="commandDropdown">Select Command:</label> | ||
<select id="commandDropdown"> | ||
<option value="/help">/help</option> | ||
<option value="/ping">/ping</option> | ||
<option value="/public-key">/public-key</option> | ||
<option value="/sign-message">/sign-message</option> | ||
<option value="/shared-secret">/shared-secret</option> | ||
<option value="/restore">/restore</option> | ||
<option value="/add-key">/add-key</option> | ||
<option value="/remove-key">/remove-key</option> | ||
<option value="/list-keys">/list-keys</option> | ||
<option value="/switch-key">/switch-key</option> | ||
<option value="/new-key">/new-key</option> | ||
<option value="/name-key">/name-key</option> | ||
<option value="/encrypt-message">/encrypt-message</option> | ||
<option value="/decrypt-message">/decrypt-message</option> | ||
<option value="/reboot">/reboot</option> | ||
<option value="/wipe">/wipe</option> | ||
</select> | ||
</div> | ||
|
||
<div> | ||
<label for="argumentsInput">Enter Arguments:</label> | ||
<input type="text" id="argumentsInput" placeholder="e.g., key data or index"> | ||
</div> | ||
|
||
<div> | ||
<button id="sendCommand">Send Command</button> | ||
</div> | ||
|
||
<div id="output"> | ||
<h2>Output</h2> | ||
<pre id="responseOutput" style="background-color: #070707;color: #ffffff;padding: 10px;"></pre> | ||
</div> | ||
|
||
<h2>Command Descriptions</h2> | ||
<table> | ||
<thead> | ||
<tr> | ||
<th width="150px">Command</th> | ||
<th width="250px">Argument 1</th> | ||
<th width="250px">Argument 2</th> | ||
<th>Description</th> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
<tr> | ||
<td>/help</td> | ||
<td>None</td> | ||
<td>None</td> | ||
<td>Returns the help text.</td> | ||
</tr> | ||
<tr> | ||
<td>/ping</td> | ||
<td>None</td> | ||
<td>None</td> | ||
<td>Checks the connection with the device.</td> | ||
</tr> | ||
<tr> | ||
<td>/public-key</td> | ||
<td>None</td> | ||
<td>None</td> | ||
<td>Returns the public key in hex format.</td> | ||
</tr> | ||
<tr> | ||
<td>/sign-message</td> | ||
<td>Message to sign in hex format</td> | ||
<td>None</td> | ||
<td>Signs the provided message with the active private key.</td> | ||
</tr> | ||
<tr> | ||
<td>/shared-secret</td> | ||
<td>Public key in hex format</td> | ||
<td>None</td> | ||
<td>Generates a shared secret using the active private key.</td> | ||
</tr> | ||
<tr> | ||
<td>/restore</td> | ||
<td>Private key in hex format</td> | ||
<td>None</td> | ||
<td>Legacy support with v0.1 installer config button.</td> | ||
</tr> | ||
<tr> | ||
<td>/add-key</td> | ||
<td>Private key in hex format</td> | ||
<td>None</td> | ||
<td>Adds a new private key to the device.</td> | ||
</tr> | ||
<tr> | ||
<td>/remove-key</td> | ||
<td>Index of the key to remove</td> | ||
<td>None</td> | ||
<td>Removes the private key at the specified index.</td> | ||
</tr> | ||
<tr> | ||
<td>/list-keys</td> | ||
<td>None</td> | ||
<td>None</td> | ||
<td>Lists all stored private keys on the device.</td> | ||
</tr> | ||
<tr> | ||
<td>/switch-key</td> | ||
<td>Index of the key to switch to</td> | ||
<td>None</td> | ||
<td>Switch the currently active private key.</td> | ||
</tr> | ||
<tr> | ||
<td>/new-key</td> | ||
<td>None</td> | ||
<td>None</td> | ||
<td>Generates a new key on the device.</td> | ||
</tr> | ||
<tr> | ||
<td>/name-key</td> | ||
<td>The name of the key</td> | ||
<td>None</td> | ||
<td>Set the name of a key. Blank removes the name.</td> | ||
</tr> | ||
<tr> | ||
<td>/encrypt-message</td> | ||
<td>3rd party public key in hex format</td> | ||
<td>The message to encrypt</td> | ||
<td>Encrypts the message on the device (NIP-04) and returns the encrypted message.</td> | ||
</tr> | ||
<tr> | ||
<td>/decrypt-message</td> | ||
<td>3rd party public key in hex format</td> | ||
<td>The message to decrypt</td> | ||
<td>Decrypts the message on the device (NIP-04) and returns the decrypted message.</td> | ||
</tr> | ||
<tr> | ||
<td>/reboot</td> | ||
<td>None</td> | ||
<td>None</td> | ||
<td>Reboots the device.</td> | ||
</tr> | ||
<tr> | ||
<td>/wipe</td> | ||
<td>None</td> | ||
<td>None</td> | ||
<td>Erases the device. All keys and config is removed.</td> | ||
</tr> | ||
</tbody> | ||
</table> | ||
</main> | ||
|
||
<script> | ||
let port; | ||
let reader; | ||
let writer; | ||
|
||
async function connectDevice() { | ||
try { | ||
port = await navigator.serial.requestPort(); | ||
await port.open({ baudRate: 9600 }); | ||
|
||
const decoder = new TextDecoderStream(); | ||
const inputDone = port.readable.pipeTo(decoder.writable); | ||
reader = decoder.readable.getReader(); | ||
|
||
const encoder = new TextEncoderStream(); | ||
const outputDone = encoder.readable.pipeTo(port.writable); | ||
writer = encoder.writable.getWriter(); | ||
|
||
// Wait for the device to initialize if needed | ||
setTimeout(() => { | ||
readLoop(); | ||
}, 500); // Delay to allow device to send initial data (adjust as necessary) | ||
|
||
alert("Device connected!"); | ||
} catch (err) { | ||
console.error('Failed to connect device:', err); | ||
alert('Failed to connect device.'); | ||
} | ||
} | ||
|
||
async function disconnectDevice() { | ||
try { | ||
if (reader) { | ||
reader.cancel(); | ||
await reader.releaseLock(); | ||
} | ||
if (writer) { | ||
await writer.close(); | ||
await writer.releaseLock(); | ||
} | ||
if (port) { | ||
await port.close(); | ||
} | ||
alert("Device disconnected!"); | ||
} catch (err) { | ||
console.error('Failed to disconnect device:', err); | ||
alert('Failed to disconnect device.'); | ||
} | ||
} | ||
|
||
async function readLoop() { | ||
let buffer = ""; // Buffer to accumulate incomplete lines | ||
try { | ||
while (port && port.readable && reader) { | ||
const { value, done } = await reader.read(); | ||
if (done) { | ||
console.log("Reader done."); | ||
break; | ||
} | ||
if (value) { | ||
buffer += value; // Append received chunk to the buffer | ||
let lines = buffer.split("\n"); // Split buffer into lines | ||
buffer = lines.pop(); // Keep the last (incomplete) line in the buffer | ||
for (let line of lines) { | ||
const trimmedLine = line.trim(); // Trim whitespace | ||
if (trimmedLine) { | ||
document.getElementById("responseOutput").textContent += trimmedLine + "\n"; | ||
} | ||
} | ||
} | ||
} | ||
// Flush any remaining data in the buffer | ||
if (buffer.trim()) { | ||
document.getElementById("responseOutput").textContent += buffer.trim() + "\n"; | ||
} | ||
} catch (err) { | ||
console.error('Error reading from device:', err); | ||
} | ||
} | ||
|
||
async function sendCommandToDevice(command) { | ||
if (!writer) { | ||
alert("Device is not connected."); | ||
return; | ||
} | ||
try { | ||
// Clear the output log before sending the command | ||
document.getElementById("responseOutput").textContent = ""; | ||
await writer.write(command + "\n"); | ||
document.getElementById("responseOutput").textContent += `Sent: ${command}\n`; | ||
} catch (err) { | ||
console.error('Error sending command:', err); | ||
alert('Failed to send command.'); | ||
} | ||
} | ||
|
||
document.getElementById('connectDevice').addEventListener('click', connectDevice); | ||
document.getElementById('disconnectDevice').addEventListener('click', disconnectDevice); | ||
|
||
document.getElementById('sendCommand').addEventListener('click', () => { | ||
const selectedCommand = document.getElementById('commandDropdown').value; | ||
const argumentsInput = document.getElementById('argumentsInput').value.trim(); | ||
const fullCommand = argumentsInput ? `${selectedCommand} ${argumentsInput}` : selectedCommand; | ||
sendCommandToDevice(fullCommand); | ||
}); | ||
</script> | ||
</body> | ||
</html> |
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
{ | ||
"name": "Nostr Signing Device", | ||
"version": "0.2", | ||
"funding_url": "https://github.com/lnbits/nostr-signing-device", | ||
"new_install_prompt_erase": true, | ||
"builds": [ | ||
{ | ||
"chipFamily": "ESP32", | ||
"parts": [ | ||
{ | ||
"path": "bootloader.bin", | ||
"offset": 4096 | ||
}, | ||
{ | ||
"path": "snsd.ino.partitions.bin", | ||
"offset": 32768 | ||
}, | ||
{ | ||
"path": "boot_app0.bin", | ||
"offset": 57344 | ||
}, | ||
{ | ||
"path": "snsd.ino.bin", | ||
"offset": 65536 | ||
} | ||
] | ||
} | ||
] | ||
} |
Binary file not shown.
Binary file not shown.
Oops, something went wrong.