import { app, BrowserWindow, clipboard, dialog, ipcMain } from 'electron'; import { get_emulator_log, kill_emulator, sapio, SapioWorkspace, start_sapio_oracle, } from './sapio'; import { readFile, writeFile } from 'fs/promises'; import { readFileSync } from 'fs'; import { preferences, Prefs } from './settings'; import { get_bitcoin_node } from './bitcoin_rpc'; import RpcError from 'bitcoin-core-ts/dist/src/errors/rpc-error'; import path from 'path'; import { setup_chat } from './chat'; export default function (window: BrowserWindow) { setup_chat(); ipcMain.handle('bitcoin::command', async (event, arg) => { const node = await get_bitcoin_node(); try { return { ok: await node.command(arg) }; } catch (r: any) { if (r instanceof RpcError) { return { err: { code: r.code, message: r.message, name: r.name }, }; } else if (r instanceof Error) { return { err: r.toString() }; } } }); ipcMain.handle('emulator::kill', (event) => { kill_emulator(); }); ipcMain.handle('emulator::start', (event) => { start_sapio_oracle(); }); ipcMain.handle('emulator::read_log', (event) => { return get_emulator_log(); }); ipcMain.handle('sapio::load_contract_list', async (event, workspace) => { const contracts = await sapio.list_contracts(workspace); return contracts; }); ipcMain.handle( 'sapio::create_contract', async (event, workspace, [which, psbt, args]) => { const result = await sapio.create_contract( workspace, which, psbt, args ); return result; } ); ipcMain.handle('sapio::show_config', async (event) => { return await sapio.show_config(); }); ipcMain.handle('sapio::load_wasm_plugin', (event, workspace) => { const plugins = dialog.showOpenDialogSync({ properties: ['openFile', 'multiSelections'], filters: [{ extensions: ['wasm'], name: 'WASM' }], }); const errs = []; if (!plugins || !plugins.length) return { err: 'No Plugin Selected' }; for (const plugin of plugins) { const loaded = sapio.load_contract_file_name(workspace, plugin); if ('err' in loaded) { return loaded; } } return { ok: null }; }); ipcMain.handle('sapio::open_contract_from_file', (event) => { const file = dialog.showOpenDialogSync(window, { properties: ['openFile'], filters: [ { extensions: ['json'], name: 'Sapio Contract Object', }, ], }); if (file && file.length === 1) { const data = readFileSync(file[0]!, { encoding: 'utf-8', }); return { ok: data }; } }); ipcMain.handle( 'sapio::compiled_contracts::list', async (event, workspace) => { return ( await SapioWorkspace.new(workspace) ).list_compiled_contracts(); } ); ipcMain.handle( 'sapio::compiled_contracts::trash', async (event, workspace, file_name) => { return ( await SapioWorkspace.new(workspace) ).trash_compiled_contract(file_name); } ); ipcMain.handle('sapio::psbt::finalize', (event, psbt) => { return sapio.psbt_finalize(psbt); }); ipcMain.handle( 'sapio::compiled_contracts::open', async (event, workspace_name, file_name) => { const workspace = await SapioWorkspace.new(workspace_name); const data = await workspace.read_bound_data_for(file_name); const name = await workspace.read_module_for(file_name); const args = await workspace.read_args_for(file_name); return { ok: { data, name, args } }; } ); ipcMain.handle('sapio::workspaces::init', async (event, workspace) => { await SapioWorkspace.new(workspace); }); ipcMain.handle('sapio::workspaces::list', async (event) => { return await SapioWorkspace.list_all(); }); ipcMain.handle('sapio::workspaces::trash', async (event, workspace) => { return (await SapioWorkspace.new(workspace)).trash_workspace(workspace); }); ipcMain.handle('write_clipboard', (event, s: string) => { clipboard.writeText(s); }); ipcMain.handle('save_psbt', async (event, psbt) => { const path = await dialog.showSaveDialog(window, { filters: [ { extensions: ['psbt'], name: 'Partially Signed Bitcoin Transaction', }, ], }); if (path.filePath) { await writeFile(path.filePath, psbt); } }); ipcMain.handle('fetch_psbt', async (event, psbt) => { const path = await dialog.showOpenDialog(window, { filters: [ { extensions: ['psbt'], name: 'Partially Signed Bitcoin Transaction', }, ], }); if (path && path.filePaths.length) { return await readFile(path.filePaths[0]!, { encoding: 'utf-8' }); } }); ipcMain.handle('save_contract', async (event, psbt) => { const path = await dialog.showSaveDialog(window, { filters: [{ extensions: ['json'], name: 'Sapio Contract Object' }], }); if (path.filePath) { await writeFile(path.filePath, psbt); } }); ipcMain.handle( 'save_settings', async (event, which: Prefs, data: string) => { return preferences.save(which, JSON.parse(data)); } ); ipcMain.handle('load_settings_sync', (event, which: Prefs) => { return preferences.data[which]; }); ipcMain.handle('select_filename', async (event) => { const path = await dialog.showOpenDialog(window); if (path && path.filePaths.length == 1) { return path.filePaths[0]!; } return null; }); }