171 lines
6.1 KiB
HTML
171 lines
6.1 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>sovereign browser — window.nostr test</title>
|
|
<style>
|
|
body {
|
|
font-family: "Courier New", Courier, monospace;
|
|
max-width: 800px;
|
|
margin: 40px auto;
|
|
padding: 20px;
|
|
background: #1a1a1a;
|
|
color: #e0e0e0;
|
|
}
|
|
h1 { color: #ff4444; }
|
|
h2 { color: #ff8888; margin-top: 30px; }
|
|
button {
|
|
font-family: monospace;
|
|
font-size: 14px;
|
|
padding: 8px 16px;
|
|
margin: 4px;
|
|
background: #333;
|
|
color: #e0e0e0;
|
|
border: 1px solid #555;
|
|
border-radius: 4px;
|
|
cursor: pointer;
|
|
}
|
|
button:hover { background: #444; border-color: #777; }
|
|
button:active { background: #222; }
|
|
pre {
|
|
background: #0d0d0d;
|
|
border: 1px solid #333;
|
|
border-radius: 4px;
|
|
padding: 12px;
|
|
overflow-x: auto;
|
|
white-space: pre-wrap;
|
|
word-wrap: break-word;
|
|
font-size: 13px;
|
|
line-height: 1.4;
|
|
}
|
|
.result { border-left: 3px solid #ff4444; padding-left: 12px; margin: 10px 0; }
|
|
.success { color: #44ff44; }
|
|
.error { color: #ff4444; }
|
|
.label { color: #888; font-size: 12px; }
|
|
#status { font-weight: bold; padding: 8px; border-radius: 4px; margin: 10px 0; }
|
|
.status-ok { background: #1a3a1a; color: #44ff44; }
|
|
.status-err { background: #3a1a1a; color: #ff4444; }
|
|
.status-wait { background: #3a3a1a; color: #ffff44; }
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<h1>sovereign browser — window.nostr test</h1>
|
|
<p class="label">This page tests the NIP-07 window.nostr API injected by the browser.</p>
|
|
|
|
<div id="status">Checking for window.nostr…</div>
|
|
|
|
<h2>1. Get Public Key</h2>
|
|
<p>Call <code>window.nostr.getPublicKey()</code> to retrieve your Nostr public key.</p>
|
|
<button onclick="testGetPublicKey()">Get Public Key</button>
|
|
<div id="pubkey-result" class="result"></div>
|
|
|
|
<h2>2. Sign Event</h2>
|
|
<p>Create and sign a kind-1 text note via <code>window.nostr.signEvent()</code>.</p>
|
|
<input type="text" id="note-text" value="Hello from sovereign browser!" style="width:400px; font-family:monospace; padding:4px; background:#333; color:#e0e0e0; border:1px solid #555; border-radius:4px;">
|
|
<button onclick="testSignEvent()">Sign Event</button>
|
|
<div id="sign-result" class="result"></div>
|
|
|
|
<h2>3. Get Relays</h2>
|
|
<p>Call <code>window.nostr.getRelays()</code> to get the browser's relay list.</p>
|
|
<button onclick="testGetRelays()">Get Relays</button>
|
|
<div id="relays-result" class="result"></div>
|
|
|
|
<h2>4. NIP-44 Encrypt/Decrypt (self)</h2>
|
|
<p>Encrypt a message to yourself and decrypt it back.</p>
|
|
<input type="text" id="encrypt-text" value="Secret test message" style="width:400px; font-family:monospace; padding:4px; background:#333; color:#e0e0e0; border:1px solid #555; border-radius:4px;">
|
|
<button onclick="testNip44()">Test NIP-44</button>
|
|
<div id="nip44-result" class="result"></div>
|
|
|
|
<script>
|
|
// Check if window.nostr is available
|
|
function checkNostr() {
|
|
var status = document.getElementById('status');
|
|
if (typeof window.nostr !== 'undefined' && window.nostr !== null) {
|
|
status.className = 'status-ok';
|
|
status.textContent = '✓ window.nostr is available';
|
|
} else {
|
|
status.className = 'status-err';
|
|
status.textContent = '✗ window.nostr is NOT available — are you running this in sovereign browser?';
|
|
}
|
|
}
|
|
|
|
function showResult(elementId, success, content) {
|
|
var el = document.getElementById(elementId);
|
|
var cls = success ? 'success' : 'error';
|
|
el.innerHTML = '<span class="' + cls + '">' + (success ? '✓' : '✗') + '</span> <pre>' + escapeHtml(content) + '</pre>';
|
|
}
|
|
|
|
function escapeHtml(text) {
|
|
var div = document.createElement('div');
|
|
div.textContent = text;
|
|
return div.innerHTML;
|
|
}
|
|
|
|
async function testGetPublicKey() {
|
|
var el = 'pubkey-result';
|
|
try {
|
|
showResult(el, true, 'Calling window.nostr.getPublicKey()…');
|
|
var pubkey = await window.nostr.getPublicKey();
|
|
showResult(el, true, 'Public key (hex): ' + pubkey);
|
|
} catch(e) {
|
|
showResult(el, false, 'Error: ' + e.message);
|
|
}
|
|
}
|
|
|
|
async function testSignEvent() {
|
|
var el = 'sign-result';
|
|
try {
|
|
var content = document.getElementById('note-text').value;
|
|
var event = {
|
|
kind: 1,
|
|
content: content,
|
|
tags: [],
|
|
created_at: Math.floor(Date.now() / 1000)
|
|
};
|
|
showResult(el, true, 'Calling window.nostr.signEvent() with:\n' + JSON.stringify(event, null, 2));
|
|
var signed = await window.nostr.signEvent(event);
|
|
showResult(el, true, 'Signed event:\n' + JSON.stringify(signed, null, 2));
|
|
} catch(e) {
|
|
showResult(el, false, 'Error: ' + e.message);
|
|
}
|
|
}
|
|
|
|
async function testGetRelays() {
|
|
var el = 'relays-result';
|
|
try {
|
|
showResult(el, true, 'Calling window.nostr.getRelays()…');
|
|
var relays = await window.nostr.getRelays();
|
|
showResult(el, true, 'Relays: ' + JSON.stringify(relays, null, 2));
|
|
} catch(e) {
|
|
showResult(el, false, 'Error: ' + e.message);
|
|
}
|
|
}
|
|
|
|
async function testNip44() {
|
|
var el = 'nip44-result';
|
|
try {
|
|
var text = document.getElementById('encrypt-text').value;
|
|
var pubkey = await window.nostr.getPublicKey();
|
|
showResult(el, true, 'Encrypting "' + text + '" to self (' + pubkey.substring(0, 16) + '…)');
|
|
|
|
var ciphertext = await window.nostr.nip44.encrypt(pubkey, text);
|
|
showResult(el, true, 'Ciphertext: ' + ciphertext.substring(0, 80) + '…');
|
|
|
|
var decrypted = await window.nostr.nip44.decrypt(pubkey, ciphertext);
|
|
if (decrypted === text) {
|
|
showResult(el, true, 'Round-trip verified!\nOriginal: ' + text + '\nDecrypted: ' + decrypted);
|
|
} else {
|
|
showResult(el, false, 'Round-trip FAILED!\nOriginal: ' + text + '\nDecrypted: ' + decrypted);
|
|
}
|
|
} catch(e) {
|
|
showResult(el, false, 'Error: ' + e.message);
|
|
}
|
|
}
|
|
|
|
// Run check on load
|
|
checkNostr();
|
|
</script>
|
|
</body>
|
|
</html>
|