All files / app preload.ts

0% Statements 0/50
0% Branches 0/3
0% Functions 0/29
0% Lines 0/45

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142                                                                                                                                                                                                                                                                                           
import type {
  LedgerRequestSignTx,
  LedgerRequestStxAddress,
} from './main/register-ledger-listeners';
import argon2 from 'argon2-browser';
import { contextBridge, ipcRenderer, shell } from 'electron';
import 'regenerator-runtime/runtime';
 
const scriptsToLoad = [];
 
Iif (process.env.NODE_ENV === 'development') {
  // Dynamically insert the DLL script in development env in the
  // renderer process
  scriptsToLoad.push('../dll/renderer.dev.dll.js');
 
  //
  // Electron 12 removed all commonjs access in renderer process
  // Webpack-dev-server uses module, this stops an error from
  // being thrown
  contextBridge.exposeInMainWorld('module', {});
}
 
if (process.env.START_HOT) {
  // Dynamically insert the bundled app script in the renderer process
  const port = 1212;
  scriptsToLoad.push(`http://localhost:${port}/dist/renderer.dev.js`);
} else {
  scriptsToLoad.push('./dist/renderer.prod.js');
}
 
contextBridge.exposeInMainWorld('electron', {
  scriptsToLoad,
  __dirname,
  __filename,
});
 
async function deriveArgon2Key({ pass, salt }: Record<'pass' | 'salt', string>) {
  const result = await argon2.hash({
    pass,
    salt,
    hashLen: 48,
    time: 44,
    mem: 1024 * 32,
    type: argon2.ArgonType.Argon2id,
  });
  return { derivedKeyHash: result.hash };
}
 
contextBridge.exposeInMainWorld('process', {
  version: process.version,
  platform: process.platform,
  nextTick: process.nextTick,
  env: {
    REACT_APP_SC_ATTR: null,
  },
});
 
const walletApi = {
  // Expose protected methods that allow the renderer process to use
  // the ipcRenderer without exposing the entire object
  store: {
    set: async (key: string, value: string | boolean) =>
      ipcRenderer.invoke('store-set', { key, value }),
    get: async (key: string) => ipcRenderer.invoke('store-get', { key }),
    delete: async (key: string) => ipcRenderer.invoke('store-delete', { key }),
    clear: async () => ipcRenderer.invoke('store-clear'),
    initialValue: () => ipcRenderer.sendSync('store-getEntireStore'),
  },
 
  deriveKey: async (args: Record<'pass' | 'salt', string>) => deriveArgon2Key(args),
 
  windowEvents: {
    blur(callback: () => void) {
      const listener = () => callback();
      ipcRenderer.on('blur', listener);
      return () => ipcRenderer.removeListener('blur', listener);
    },
    focus(callback: () => void) {
      const listener = () => callback();
      ipcRenderer.on('focus', listener);
      return () => ipcRenderer.removeListener('focus', listener);
    },
  },
 
  openExternalLink: (url: string) => shell.openExternal(url),
 
  reloadApp: () => ipcRenderer.invoke('reload-app'),
 
  contextMenu: (menuItems: any) => ipcRenderer.send('context-menu-open', { menuItems }),
 
  closeWallet: () => ipcRenderer.send('closeWallet'),
 
  getUserDataPath: () => ipcRenderer.sendSync('get-user-data-path'),
 
  theme: {
    getCurrentTheme() {
      return ipcRenderer.sendSync('theme:get-current');
    },
    toggleMode() {
      return ipcRenderer.invoke('theme:toggle-mode');
    },
    setSystemMode() {
      return ipcRenderer.invoke('theme:set-system-mode');
    },
  },
 
  /**
   * This method is needed to share the user's diagnostics preference
   * with the `main` script, that otherwise has no way of determining
   * what this state is.
   */
  setDiagnosticPermission(updatedPermission: boolean) {
    return ipcRenderer.send('set-diagnostics-permission', updatedPermission);
  },
 
  ledger: {
    createListener: () => ipcRenderer.send('create-ledger-listener'),
    removeListener: () => ipcRenderer.send('remove-ledger-listener'),
    async signTransaction(unsignedTxHex: string) {
      return ipcRenderer.invoke('ledger-request-sign-tx', unsignedTxHex) as LedgerRequestSignTx;
    },
    async requestAndConfirmStxAddress() {
      return ipcRenderer.invoke('ledger-request-stx-address') as LedgerRequestStxAddress;
    },
    async showStxAddress() {
      return ipcRenderer.invoke('ledger-show-stx-address');
    },
  },
};
 
contextBridge.exposeInMainWorld('main', walletApi);
 
declare global {
  const main: typeof walletApi;
}
 
function postMessageToApp(data: unknown) {
  window.postMessage(data, '*');
}
 
ipcRenderer.on('message-event', (_event, data) => postMessageToApp({ ...data }));