144 lines
5.2 KiB
HTML
144 lines
5.2 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Link Nostr Identity</title>
|
|
<link rel="stylesheet" href="css.css">
|
|
</head>
|
|
<body>
|
|
<h1>Link Your Nostr Identity</h1>
|
|
<p>Connect your npub to your Matrix display name so you can vote.</p>
|
|
|
|
<div id="auth_section">
|
|
<div id="nip07_status" class="info-box" style="display:none;">
|
|
Nostr browser extension detected.
|
|
</div>
|
|
|
|
<label for="display_name">Matrix Display Name:</label>
|
|
<input type="text" id="display_name" placeholder="Enter your Matrix display name exactly">
|
|
|
|
<label for="npub_input">Nostr Public Key (npub):</label>
|
|
<input type="text" id="npub_input" placeholder="npub1...">
|
|
|
|
<button id="connect_btn" onclick="connectNip07()">Connect AlbyHub</button>
|
|
<button id="link_btn" onclick="linkNpub()">Link & Sign</button>
|
|
|
|
<div id="status"></div>
|
|
</div>
|
|
|
|
<script>
|
|
let currentNpub = null;
|
|
|
|
async function connectNip07() {
|
|
if (!window.nostr) {
|
|
setStatus('No Nostr browser extension detected. Please enter your npub manually.', true);
|
|
return;
|
|
}
|
|
try {
|
|
const pubkey = await window.nostr.getPublicKey();
|
|
const resp = await fetch('encode_npub', {
|
|
method: 'POST',
|
|
headers: {'Content-Type': 'application/json'},
|
|
body: JSON.stringify({hex: pubkey})
|
|
});
|
|
if (resp.ok) {
|
|
const data = await resp.json();
|
|
document.getElementById('npub_input').value = data.npub;
|
|
currentNpub = data.npub;
|
|
setStatus('Connected! Npub loaded from extension.');
|
|
} else {
|
|
document.getElementById('npub_input').value = pubkey;
|
|
currentNpub = pubkey;
|
|
setStatus('Connected! Paste this as npub if needed: ' + pubkey);
|
|
}
|
|
} catch (err) {
|
|
setStatus('Error connecting to extension: ' + err.message, true);
|
|
}
|
|
}
|
|
|
|
async function linkNpub() {
|
|
const displayName = document.getElementById('display_name').value.trim();
|
|
const npub = document.getElementById('npub_input').value.trim();
|
|
|
|
if (!displayName) {
|
|
setStatus('Please enter your Matrix display name.', true);
|
|
return;
|
|
}
|
|
if (!npub) {
|
|
setStatus('Please enter your npub or connect AlbyHub.', true);
|
|
return;
|
|
}
|
|
|
|
setStatus('Requesting signature...');
|
|
|
|
try {
|
|
let npubHex = npub;
|
|
|
|
const decodeResp = await fetch('decode_npub', {
|
|
method: 'POST',
|
|
headers: {'Content-Type': 'application/json'},
|
|
body: JSON.stringify({npub: npub})
|
|
});
|
|
|
|
if (!decodeResp.ok) {
|
|
if (!window.nostr) {
|
|
setStatus('Could not decode npub. Please install a Nostr extension.', true);
|
|
return;
|
|
}
|
|
setStatus('Could not decode npub via server.', true);
|
|
return;
|
|
}
|
|
|
|
const decodeData = await decodeResp.json();
|
|
npubHex = decodeData.hex;
|
|
|
|
const slug = window.location.pathname.split('/')[1];
|
|
const linkMsg = `Link npub ${npubHex} to Matrix user ${displayName} for room ${slug}`;
|
|
|
|
let signedEvent;
|
|
if (window.nostr) {
|
|
signedEvent = await window.nostr.signEvent({
|
|
created_at: Math.floor(Date.now() / 1000),
|
|
kind: 1,
|
|
tags: [],
|
|
content: linkMsg
|
|
});
|
|
} else {
|
|
setStatus('No Nostr extension available. Please install AlbyHub or another NIP-07 signer.', true);
|
|
return;
|
|
}
|
|
|
|
setStatus('Sending link request...');
|
|
|
|
const resp = await fetch('linkNpub', {
|
|
method: 'POST',
|
|
headers: {'Content-Type': 'application/json'},
|
|
body: JSON.stringify({
|
|
display_name: displayName,
|
|
npub: npub,
|
|
signed_event: signedEvent
|
|
})
|
|
});
|
|
|
|
if (resp.ok) {
|
|
setStatus('Successfully linked! You can now <a href="/">go vote</a>.');
|
|
document.getElementById('link_btn').disabled = true;
|
|
} else {
|
|
const text = await resp.text();
|
|
setStatus('Error: ' + text, true);
|
|
}
|
|
} catch (err) {
|
|
setStatus('Error: ' + err.message, true);
|
|
}
|
|
}
|
|
|
|
function setStatus(msg, isError) {
|
|
const el = document.getElementById('status');
|
|
el.innerHTML = msg;
|
|
el.className = isError ? 'error' : 'success';
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|