archy/neode-ui/public/nostr-provider.js
2026-03-12 12:56:59 +00:00

80 lines
2.3 KiB
JavaScript

/**
* NIP-07 Nostr Provider Shim
*
* Injected into proxied iframe apps via nginx sub_filter.
* Implements window.nostr interface (getPublicKey, signEvent)
* by communicating with the parent Archipelago frame via postMessage.
*
* Security: validates postMessage origin, never exposes secret key.
*/
(function () {
'use strict';
// Only inject if we're inside an iframe
if (window === window.top) return;
// Don't override existing NIP-07 extensions
if (window.nostr) return;
var pending = {};
var nextId = 1;
function request(method, params) {
return new Promise(function (resolve, reject) {
var id = nextId++;
pending[id] = { resolve: resolve, reject: reject };
window.parent.postMessage(
{ type: 'nostr-request', id: id, method: method, params: params || {} },
'*'
);
// Timeout after 30 seconds
setTimeout(function () {
if (pending[id]) {
pending[id].reject(new Error('NIP-07 request timed out'));
delete pending[id];
}
}, 30000);
});
}
window.addEventListener('message', function (event) {
if (!event.data || event.data.type !== 'nostr-response') return;
var handler = pending[event.data.id];
if (!handler) return;
delete pending[event.data.id];
if (event.data.error) {
handler.reject(new Error(event.data.error));
} else {
handler.resolve(event.data.result);
}
});
window.nostr = {
getPublicKey: function () {
return request('getPublicKey');
},
signEvent: function (event) {
return request('signEvent', { event: event });
},
getRelays: function () {
return request('getRelays');
},
nip04: {
encrypt: function (pubkey, plaintext) {
return request('nip04.encrypt', { pubkey: pubkey, plaintext: plaintext });
},
decrypt: function (pubkey, ciphertext) {
return request('nip04.decrypt', { pubkey: pubkey, ciphertext: ciphertext });
},
},
nip44: {
encrypt: function (pubkey, plaintext) {
return request('nip44.encrypt', { pubkey: pubkey, plaintext: plaintext });
},
decrypt: function (pubkey, ciphertext) {
return request('nip44.decrypt', { pubkey: pubkey, ciphertext: ciphertext });
},
},
};
})();