From 1fe6391b7bf5e2723c49a47a73e9d91eff677ec0 Mon Sep 17 00:00:00 2001 From: Einliterflasche <81313171+Einliterflasche@users.noreply.github.com> Date: Sat, 31 Aug 2024 11:41:33 +0200 Subject: [PATCH] ci: auto generate typescript bindings (#56) This PR - removes `tauriModel.ts` from git and instead - generates `tauriModel.ts` everytime `vite` starts or `vite` detects a change in `swap/src/` To do that I have introduced the `gen-bindings` and `check-bindings` commands as well as improved documentation. Following this PR, the Typescript bindings to our Tauri commands will be automatically re-generated upon the instant a source file is changed! This closes #49 --- src-gui/.gitignore | 3 + src-gui/README.md | 37 +++- src-gui/package.json | 4 + src-gui/src/models/tauriModel.ts | 284 ------------------------------- src-gui/vite.config.ts | 26 ++- src-gui/yarn.lock | 14 ++ 6 files changed, 76 insertions(+), 292 deletions(-) delete mode 100644 src-gui/src/models/tauriModel.ts diff --git a/src-gui/.gitignore b/src-gui/.gitignore index 289e710c0..12df96313 100644 --- a/src-gui/.gitignore +++ b/src-gui/.gitignore @@ -23,3 +23,6 @@ dist-ssr *.njsproj *.sln *.sw? + +# Autogenerated bindings +src/models/tauriModel.ts diff --git a/src-gui/README.md b/src-gui/README.md index 2e7cd9c9f..e34f93a63 100644 --- a/src-gui/README.md +++ b/src-gui/README.md @@ -1,13 +1,40 @@ -# Tauri + React + Typescript - -This template should help get you started developing with Tauri, React and Typescript in Vite. - ## Recommended IDE Setup - [VS Code](https://code.visualstudio.com/) + [Tauri](https://marketplace.visualstudio.com/items?itemName=tauri-apps.tauri-vscode) + [rust-analyzer](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer) +## Requirements + +- For compiling the Rust code: `cargo` and `cargo tauri` ([installation](https://v2.tauri.app/reference/cli/)) +- For running the Typescript code: `node` and `yarn` +- For formatting and bindings: `dprint` (`cargo install dprint@0.39.1`) and `typeshare` (`cargo install typeshare-cli`) +- If you are on Windows and you want to use the `check-bindings` command you'll need to manually install the GNU DiffUtils ([installation](https://gnuwin32.sourceforge.net/packages/diffutils.htm)) and GNU CoreUtils ([installtion](https://gnuwin32.sourceforge.net/packages/coreutils.htm)). Remember to add the installation path (probably `C:\Program Files (x86)\GnuWin32\bin`) to the `PATH` in your enviroment variables. + +## Start development servers + +For development, we need to run both `vite` and `tauri` servers: + +```bash +cd src-gui +yarn install && yarn run dev +# let this run +``` + +```bash +cd src-tauri +cargo tauri dev +# let this run as well +``` + ## Generate bindings for Tauri API +Running `yarn run dev` or `yarn build` should automatically re-build the Typescript bindings whenever something changes. You can also manually trigger this using the `gen-bindings` command: + +```bash +yarn run gen-bindings +``` + +You can also check whether the current bindings are up to date: + ```bash -typeshare --lang=typescript --output-file ./src/models/tauriModel.ts ../swap/src +yarn run check-bindings ``` diff --git a/src-gui/package.json b/src-gui/package.json index b2ba3c5ec..a30721225 100644 --- a/src-gui/package.json +++ b/src-gui/package.json @@ -4,7 +4,10 @@ "version": "0.0.0", "type": "module", "scripts": { + "check-bindings": "typeshare --lang=typescript --output-file __temp_bindings.ts ../swap/src && dprint fmt __temp_bindings.ts && diff -wbB __temp_bindings.ts ./src/models/tauriModel.ts && rm __temp_bindings.ts", + "gen-bindings": "typeshare --lang=typescript --output-file ./src/models/tauriModel.ts ../swap/src && dprint fmt ./src/models/tauriModel.ts", "dev": "vite", + "prebuild": "yarn run gen-bindings", "build": "tsc && vite build", "preview": "vite preview", "tauri": "tauri" @@ -48,6 +51,7 @@ "typescript": "^5.2.2", "typescript-eslint": "^8.1.0", "vite": "^5.3.1", + "vite-plugin-watch": "^0.3.1", "vite-tsconfig-paths": "^4.3.2" } } diff --git a/src-gui/src/models/tauriModel.ts b/src-gui/src/models/tauriModel.ts deleted file mode 100644 index c83e2af4a..000000000 --- a/src-gui/src/models/tauriModel.ts +++ /dev/null @@ -1,284 +0,0 @@ -/* - Generated by typeshare 1.9.2 -*/ - -/** - * Represent a timelock, expressed in relative block height as defined in - * [BIP68](https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki). - * E.g. The timelock expires 10 blocks after the reference transaction is - * mined. - */ -export type CancelTimelock = number; - -/** - * Represent a timelock, expressed in relative block height as defined in - * [BIP68](https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki). - * E.g. The timelock expires 10 blocks after the reference transaction is - * mined. - */ -export type PunishTimelock = number; - -export type Amount = number; - -export interface BuyXmrArgs { - seller: string; - bitcoin_change_address: string; - monero_receive_address: string; -} - -/** Represents a quote for buying XMR. */ -export interface BidQuote { - /** The price at which the maker is willing to buy at. */ - price: number; - /** - * The minimum quantity the maker is willing to buy. - * #[typeshare(serialized_as = "number")] - */ - min_quantity: number; - /** The maximum quantity the maker is willing to buy. */ - max_quantity: number; -} - -export interface BuyXmrResponse { - swap_id: string; - quote: BidQuote; -} - -export interface ResumeSwapArgs { - swap_id: string; -} - -export interface ResumeSwapResponse { - result: string; -} - -export interface CancelAndRefundArgs { - swap_id: string; -} - -export interface MoneroRecoveryArgs { - swap_id: string; -} - -export interface WithdrawBtcArgs { - amount?: number; - address: string; -} - -export interface WithdrawBtcResponse { - amount: number; - txid: string; -} - -export interface ListSellersArgs { - rendezvous_point: string; -} - -export interface StartDaemonArgs { - server_address: string; -} - -export interface GetSwapInfoArgs { - swap_id: string; -} - -export interface Seller { - peer_id: string; - addresses: string[]; -} - -export type ExpiredTimelocks = - | { type: "None", content: { - blocks_left: number; -}} - | { type: "Cancel", content: { - blocks_left: number; -}} - | { type: "Punish", content?: undefined }; - -export interface GetSwapInfoResponse { - swap_id: string; - seller: Seller; - completed: boolean; - start_date: string; - state_name: string; - xmr_amount: number; - btc_amount: number; - tx_lock_id: string; - tx_cancel_fee: number; - tx_refund_fee: number; - tx_lock_fee: number; - btc_refund_address: string; - cancel_timelock: CancelTimelock; - punish_timelock: PunishTimelock; - timelock?: ExpiredTimelocks; -} - -export interface BalanceArgs { - force_refresh: boolean; -} - -export interface BalanceResponse { - balance: number; -} - -export interface GetHistoryArgs { -} - -export interface GetHistoryEntry { - swap_id: string; - state: string; -} - -export interface GetHistoryResponse { - swaps: GetHistoryEntry[]; -} - -export interface SuspendCurrentSwapResponse { - swap_id: string; -} - -export interface BuyXmrArgs { - seller: string; - bitcoin_change_address: string; - monero_receive_address: string; -} - -export interface BuyXmrResponse { - swap_id: string; - quote: BidQuote; -} - -export interface ResumeSwapArgs { - swap_id: string; -} - -export interface ResumeSwapResponse { - result: string; -} - -export interface CancelAndRefundArgs { - swap_id: string; -} - -export interface MoneroRecoveryArgs { - swap_id: string; -} - -export interface WithdrawBtcArgs { - amount?: number; - address: string; -} - -export interface WithdrawBtcResponse { - amount: number; - txid: string; -} - -export interface ListSellersArgs { - rendezvous_point: string; -} - -export interface StartDaemonArgs { - server_address: string; -} - -export interface GetSwapInfoArgs { - swap_id: string; -} - -export interface GetSwapInfoResponse { - swap_id: string; - seller: Seller; - completed: boolean; - start_date: string; - state_name: string; - xmr_amount: number; - btc_amount: number; - tx_lock_id: string; - tx_cancel_fee: number; - tx_refund_fee: number; - tx_lock_fee: number; - btc_refund_address: string; - cancel_timelock: CancelTimelock; - punish_timelock: PunishTimelock; - timelock?: ExpiredTimelocks; -} - -export interface BalanceArgs { - force_refresh: boolean; -} - -export interface BalanceResponse { - balance: number; -} - -export interface GetHistoryArgs { -} - -export interface GetHistoryEntry { - swap_id: string; - state: string; -} - -export interface GetHistoryResponse { - swaps: GetHistoryEntry[]; -} - -export interface Seller { - peer_id: string; - addresses: string[]; -} - -export interface SuspendCurrentSwapResponse { - swap_id: string; -} - -export type TauriSwapProgressEvent = - | { type: "Initiated", content?: undefined } - | { type: "ReceivedQuote", content: BidQuote } - | { type: "WaitingForBtcDeposit", content: { - deposit_address: string; - max_giveable: number; - min_deposit_until_swap_will_start: number; - max_deposit_until_maximum_amount_is_reached: number; - min_bitcoin_lock_tx_fee: number; - quote: BidQuote; -}} - | { type: "Started", content: { - btc_lock_amount: number; - btc_tx_lock_fee: number; -}} - | { type: "BtcLockTxInMempool", content: { - btc_lock_txid: string; - btc_lock_confirmations: number; -}} - | { type: "XmrLockTxInMempool", content: { - xmr_lock_txid: string; - xmr_lock_tx_confirmations: number; -}} - | { type: "XmrLocked", content?: undefined } - | { type: "BtcRedeemed", content?: undefined } - | { type: "XmrRedeemInMempool", content: { - xmr_redeem_txid: string; - xmr_redeem_address: string; -}} - | { type: "BtcCancelled", content: { - btc_cancel_txid: string; -}} - | { type: "BtcRefunded", content: { - btc_refund_txid: string; -}} - | { type: "BtcPunished", content?: undefined } - | { type: "AttemptingCooperativeRedeem", content?: undefined } - | { type: "CooperativeRedeemAccepted", content?: undefined } - | { type: "CooperativeRedeemRejected", content: { - reason: string; -}} - | { type: "Released", content?: undefined }; - -export interface TauriSwapProgressEventWrapper { - swap_id: string; - event: TauriSwapProgressEvent; -} - diff --git a/src-gui/vite.config.ts b/src-gui/vite.config.ts index 4a2412ecb..bb11f9059 100644 --- a/src-gui/vite.config.ts +++ b/src-gui/vite.config.ts @@ -2,13 +2,33 @@ import react from "@vitejs/plugin-react"; import { internalIpV4 } from "internal-ip"; import { defineConfig } from "vite"; import tsconfigPaths from "vite-tsconfig-paths"; +import { watch } from "vite-plugin-watch"; +import path from "path"; -// @ts-expect-error process is a nodejs global const mobile = !!/android|ios/.exec(process.env.TAURI_ENV_PLATFORM); // https://vitejs.dev/config/ export default defineConfig(async () => ({ - plugins: [react(), tsconfigPaths()], + plugins: [ + react(), + tsconfigPaths(), + // automatically regenerate the typescript bindings when there's a change + watch({ + pattern: ["../swap/src/**/*"], + command: "yarn run gen-bindings", + silent: true, + }), + // this makes it so that the former plugin can recognize changes to the swap crate + { + name: "watch-swap", + configureServer(server) { + server.watcher.add(path.resolve(__dirname, "../swap/src")); + }, + }, + // VitePluginRestart({ + // restart: ["../swap/src/**/*"] + // }) + ], // Vite options tailored for Tauri development and only applied in `tauri dev` or `tauri build` // // 1. prevent vite from obscuring rust errors @@ -27,7 +47,7 @@ export default defineConfig(async () => ({ : undefined, watch: { // 3. tell vite to ignore watching `src-tauri` - ignored: ["**/src-tauri/**"], + ignored: ["**/src-tauri/**", "!../swap/**/*"], }, }, })); diff --git a/src-gui/yarn.lock b/src-gui/yarn.lock index e76385c10..eccb1e90b 100644 --- a/src-gui/yarn.lock +++ b/src-gui/yarn.lock @@ -2372,6 +2372,13 @@ minimatch@^3.1.2: dependencies: brace-expansion "^1.1.7" +minimatch@^5.1.1: + version "5.1.6" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" + integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== + dependencies: + brace-expansion "^2.0.1" + minimatch@^9.0.4: version "9.0.5" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" @@ -3294,6 +3301,13 @@ virtua@^0.33.2: resolved "https://registry.yarnpkg.com/virtua/-/virtua-0.33.2.tgz#b9596387bc77664293359d438319e81180a0e051" integrity sha512-4NgtryQH/idQ3oKkwM6DRCoCsn+IrjrStGcDOARPdlY7zIg0AtTcUq24nysM8YyHoS6KhqcVe8A3+lHJidNQWA== +vite-plugin-watch@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/vite-plugin-watch/-/vite-plugin-watch-0.3.1.tgz#5000f7ded6eb1c42e9483d6ea3d812061ab8188f" + integrity sha512-tmLJ5tqSqXY7wSXoM8+huOgbictUG6SKLh/tZ6LAY51KPSAnPBr0dYwyxPPPQm+JgIIBbKSyNnPHpW11ad+qlw== + dependencies: + minimatch "^5.1.1" + vite-tsconfig-paths@^4.3.2: version "4.3.2" resolved "https://registry.yarnpkg.com/vite-tsconfig-paths/-/vite-tsconfig-paths-4.3.2.tgz#321f02e4b736a90ff62f9086467faf4e2da857a9"