signer.mjs raw
1 // TinyJS Runtime — Signer Bridge
2 // Wraps window.nostr (NIP-07) and window.nostr.smesh (management API).
3 // Called by generated Go→JS signer jsbridge code.
4 //
5 // All string parameters are coerced with '' + x because Moxie strings are
6 // Slice objects. The extension bridge JSON-serialises arguments, and
7 // JSON.stringify(Slice) produces garbage. Coercion triggers Slice.toString()
8 // which decodes the bytes to a JS string.
9
10 function _str(v) { return '' + v; }
11
12 export function HasSigner() {
13 return typeof window !== 'undefined' && typeof window.nostr !== 'undefined';
14 }
15
16 export function HasMLS() {
17 return HasSigner() && !!(window.nostr.mls);
18 }
19
20 export function GetPublicKey(fn) {
21 if (!HasSigner()) { fn(''); return; }
22 window.nostr.getPublicKey()
23 .then(function(k) { fn(k); })
24 .catch(function() { fn(''); });
25 }
26
27 export function SignEvent(eventJSON, fn) {
28 if (!HasSigner()) { fn(''); return; }
29 var ev = JSON.parse(_str(eventJSON));
30 window.nostr.signEvent(ev)
31 .then(function(signed) { fn(JSON.stringify(signed)); })
32 .catch(function() { fn(''); });
33 }
34
35 export function Nip04Decrypt(peerPubkey, ciphertext, fn) {
36 if (!HasSigner() || !window.nostr.nip04) { fn(''); return; }
37 window.nostr.nip04.decrypt(_str(peerPubkey), _str(ciphertext))
38 .then(function(pt) { fn(pt); })
39 .catch(function() { fn(''); });
40 }
41
42 export function Nip04Encrypt(peerPubkey, plaintext, fn) {
43 if (!HasSigner() || !window.nostr.nip04) { fn(''); return; }
44 window.nostr.nip04.encrypt(_str(peerPubkey), _str(plaintext))
45 .then(function(ct) { fn(ct); })
46 .catch(function() { fn(''); });
47 }
48
49 export function Nip44Decrypt(peerPubkey, ciphertext, fn) {
50 if (!HasSigner() || !window.nostr.nip44) { fn(''); return; }
51 window.nostr.nip44.decrypt(_str(peerPubkey), _str(ciphertext))
52 .then(function(pt) { fn(pt); })
53 .catch(function() { fn(''); });
54 }
55
56 export function Nip44Encrypt(peerPubkey, plaintext, fn) {
57 if (!HasSigner() || !window.nostr.nip44) { fn(''); return; }
58 window.nostr.nip44.encrypt(_str(peerPubkey), _str(plaintext))
59 .then(function(ct) { fn(ct); })
60 .catch(function() { fn(''); });
61 }
62
63 // --- Smesh management API (window.nostr.smesh) ---
64
65 function _smesh() {
66 return (typeof window !== 'undefined' && window.nostr && window.nostr.smesh) || null;
67 }
68
69 export function IsInstalled(fn) {
70 var s = _smesh();
71 if (s && s.isInstalled) {
72 var result = s.isInstalled();
73 if (result && typeof result.then === 'function') {
74 result.then(function(ok) { fn(!!ok); }).catch(function() { fn(false); });
75 } else {
76 fn(!!result);
77 }
78 } else {
79 fn(false);
80 }
81 }
82
83 export function GetVaultStatus(fn) {
84 var s = _smesh();
85 if (s && s.getVaultStatus) {
86 s.getVaultStatus().then(function(st) { fn(st); }).catch(function() { fn('none'); });
87 } else {
88 fn('none');
89 }
90 }
91
92 export function CreateVault(password, fn) {
93 var s = _smesh();
94 if (s && s.createVault) {
95 s.createVault(_str(password)).then(function(ok) { fn(!!ok); }).catch(function() { fn(false); });
96 } else {
97 fn(false);
98 }
99 }
100
101 export function UnlockVault(password, fn) {
102 var s = _smesh();
103 if (s && s.unlockVault) {
104 s.unlockVault(_str(password)).then(function(ok) { fn(!!ok); }).catch(function() { fn(false); });
105 } else {
106 fn(false);
107 }
108 }
109
110 export function LockVault(fn) {
111 var s = _smesh();
112 if (s && s.lockVault) {
113 s.lockVault().then(function() { fn(); }).catch(function() { fn(); });
114 } else {
115 fn();
116 }
117 }
118
119 export function ListIdentities(fn) {
120 var s = _smesh();
121 if (s && s.listIdentities) {
122 s.listIdentities()
123 .then(function(list) { fn(typeof list === 'string' ? list : JSON.stringify(list)); })
124 .catch(function() { fn('[]'); });
125 } else {
126 fn('[]');
127 }
128 }
129
130 export function AddIdentity(nsec, fn) {
131 var s = _smesh();
132 if (s && s.addIdentity) {
133 s.addIdentity(_str(nsec)).then(function(ok) { fn(!!ok); }).catch(function() { fn(false); });
134 } else {
135 fn(false);
136 }
137 }
138
139 export function NsecLogin(nsec, fn) {
140 var s = _smesh();
141 if (s && s.nsecLogin) {
142 s.nsecLogin(_str(nsec)).then(function(ok) { fn(!!ok); }).catch(function() { fn(false); });
143 } else {
144 fn(false);
145 }
146 }
147
148 export function SwitchIdentity(pubkey, fn) {
149 var s = _smesh();
150 if (s && s.switchIdentity) {
151 s.switchIdentity(_str(pubkey)).then(function(ok) { fn(!!ok); }).catch(function() { fn(false); });
152 } else {
153 fn(false);
154 }
155 }
156
157 export function ExportVault(password, fn) {
158 var s = _smesh();
159 if (s && s.exportVault) {
160 s.exportVault(_str(password)).then(function(data) {
161 // data may be an object (parsed by ext.mjs) or a string
162 if (typeof data === 'object' && data !== null) {
163 fn(JSON.stringify(data));
164 } else {
165 fn(data || '');
166 }
167 }).catch(function() { fn(''); });
168 } else {
169 fn('');
170 }
171 }
172
173 export function ImportVault(data, fn) {
174 var s = _smesh();
175 if (s && s.importVault) {
176 s.importVault(_str(data)).then(function(ok) { fn(!!ok); }).catch(function() { fn(false); });
177 } else {
178 fn(false);
179 }
180 }
181
182 export function RemoveIdentity(pubkey, fn) {
183 var s = _smesh();
184 if (s && s.removeIdentity) {
185 s.removeIdentity(_str(pubkey)).then(function(ok) { fn(!!ok); }).catch(function() { fn(false); });
186 } else {
187 fn(false);
188 }
189 }
190
191 // --- HD keychain ---
192
193 export function GenerateMnemonic(fn) {
194 var s = _smesh();
195 if (s && s.generateMnemonic) {
196 s.generateMnemonic().then(function(m) { fn(m || ''); }).catch(function() { fn(''); });
197 } else {
198 fn('');
199 }
200 }
201
202 export function ValidateMnemonic(mnemonic, fn) {
203 var s = _smesh();
204 if (s && s.validateMnemonic) {
205 s.validateMnemonic(_str(mnemonic)).then(function(ok) { fn(!!ok); }).catch(function() { fn(false); });
206 } else {
207 fn(false);
208 }
209 }
210
211 export function CreateHDVault(password, name, fn) {
212 var s = _smesh();
213 if (s && s.createHDVault) {
214 s.createHDVault(_str(password), _str(name)).then(function(m) { fn(m || ''); }).catch(function() { fn(''); });
215 } else {
216 fn('');
217 }
218 }
219
220 export function RestoreHDVault(password, mnemonic, name, fn) {
221 var s = _smesh();
222 if (s && s.restoreHDVault) {
223 s.restoreHDVault(_str(password), _str(mnemonic), _str(name)).then(function(ok) { fn(!!ok); }).catch(function() { fn(false); });
224 } else {
225 fn(false);
226 }
227 }
228
229 export function DeriveIdentity(name, fn) {
230 var s = _smesh();
231 if (s && s.deriveIdentity) {
232 s.deriveIdentity(_str(name)).then(function(pk) { fn(pk || ''); }).catch(function() { fn(''); });
233 } else {
234 fn('');
235 }
236 }
237
238 export function GetMnemonic(fn) {
239 var s = _smesh();
240 if (s && s.getMnemonic) {
241 s.getMnemonic().then(function(m) { fn(m || ''); }).catch(function() { fn(''); });
242 } else {
243 fn('');
244 }
245 }
246
247 export function ProbeAccount(index, fn) {
248 var s = _smesh();
249 if (s && s.probeAccount) {
250 s.probeAccount(index).then(function(pk) { fn(pk || ''); }).catch(function() { fn(''); });
251 } else {
252 fn('');
253 }
254 }
255
256 export function IsHD(fn) {
257 var s = _smesh();
258 if (s && s.isHD) {
259 s.isHD().then(function(ok) { fn(!!ok); }).catch(function() { fn(false); });
260 } else {
261 fn(false);
262 }
263 }
264
265 export function ResetExtension(fn) {
266 var s = _smesh();
267 if (s && s.resetExtension) {
268 s.resetExtension().then(function(ok) { fn(!!ok); }).catch(function() { fn(false); });
269 } else {
270 fn(false);
271 }
272 }
273