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